#Multi-objective evolving Monsters @use PhysicalControl. @use Movie. @use Mobile. @use Stationary. @use File. @include "Constants.tz". @include "FreeNetwork.tz". @include "FreeNetGa.tz". @include "NSGA2.tz". @include "ZScoresGA.tz" @include "MaxDominate.tz" @include "GraphicsHandler.tz". @include "Environment.tz". @include "Log.tz". @include "Math3D.tz". @include "Agent.tz". @include "Triangulate.tz". @include "Player.tz". @include "HUD.tz". @include "NetViewer.tz". @include "Sensor.tz". @include "Monster.tz". @include "CommandLineHandler.tz". @include "NetIO.tz". @include "EvolutionMode.tz". @include "BehaviorState.tz". @include "UnitTest.tz". Controller SimulationControl. PhysicalControl : SimulationControl { + variables: # Auxillary classes myHUD (object). # HUD view (object). # NetViewer triangulate (object). # Triangulate math (object). # Math3D netIO (object). # NetIO log (object). # Log graphics (object). # GraphicsHandler commandline (object). # CommandLineHandler evolution-mode (object). # EvolutionModeArbitrator behavior-state (object). # BehaviorState mode-arbitrator (object). # ModeArbitrator main-camera (object). # Camera # IO hide-text (int). write-settings-and-exit (int). settings-file (string). settings-path (string). loaded-log-objects (list). loaded-fitnesses (list). loaded-inputs (list). loaded-input-args (list). loaded-input-ranges (list). excluded-fitnesses (list). load (int). resume (int). overwrite-log (int). user-save (int). user-end (int). file-path (string). inputPath (string). inputFiles (string). experiment-theme (string). file-output (int). # Game mode tasks (list). home-stretch-counter (int). home-stretch (int). skip-trial (int). user-increase-challenge (int). num-evals (int). current-iteration (int). current-game-mode (int). current-game-mode-counter (int). goal (object). # For player player (object). # Player deaths (int). previous-strategy (int). strategy-switches (int). player-shoots (int). # For monsters stay-bound (int). shuffle-offset (int). subpop-size (int). number-of-subpops (int). monsters-from-each-subpop (int). monsters (list). monster-starting-weights (list). kills-last-gen (int). additional-input-info (list). # For evolution use-shaping (int). recency-weighted-alpha (double). drop-defeated (int). homogeneous (int). behavior-diversity (int). random-behavior-syllabus (int). stagnation-counter (int). children-per-parent (int). ga (object). # FreeNetGA selection (object). # NSGA2 or ZScoresGA or MaxDominate fitness-info-list (list). current-fitnesses (list). current-mode-usage (list). parent-brains (list). #parent-mode-usage (list). parent-fitnesses (list). child-brains (list). #child-mode-usage (list). child-fitnesses (list). current-population (int). current-population-num (int). player-powerups (int). phase (int). generation (int). # Diversity diversity-fitness-index (int). current-behavior-vectors (list). parent-behavior-vectors (list). # Stats current-eval (int). num-achieved-all-goals (int). group-score (double). ave-group-score (double). ave-group-fight-score (double). ave-group-pred-score (double). player-score (double). ave-player-score (double). ave-player-fight-score (double). ave-player-prey-score (double). type-trials (list). type-trials-for-brains (list). ratio-children-in-new-pop (double). # Movie movie (object). # Movie + to read-auto-resume-info: handle (object). print "Reading auto-resume info". handle = new File. handle open-for-reading with-file (commandline string-param named "auto-resume"). self set-last-path-saved to (handle read-line). self set-last-file-saved to (handle read-line). handle close. + to create-auto-resume-file named file (string): handle (object). print "Create auto-resume file: $file". handle = new File. handle open-for-writing with-file file. handle write-line text (commandline string-param named "last-path-saved"). handle write-line text (commandline string-param named "last-file-saved"). handle close. + to file-exists named file (string): handle (object). eof (int). temp (string). print "Does $file exist?". if (file == ""): return 0. else { handle = new File. handle open-for-appending with-file file. handle close. handle open-for-reading with-file file. temp = handle read-line. eof = (handle is-end-of-file). handle close. print "$temp EOF: $eof". return (!eof). } + to click on theObject (object): if (theObject) && (theObject can-respond to "click") : { theObject click. } # id: a subpopulation index # population-slot: index within individual subpopulation + to get-type-trials-for sub id (int) slot population-slot (int): return type-trials-for-brains{id}{population-slot}. + to get-speed-difficulty: return (commandline num-param named "speed-difficulty"). # sd: 0 <= sd <= 1.0 + to set-speed-difficulty to sd (double): stagnation-counter = 0. commandline set-num-param named "speed-difficulty" to sd. + to next-in-speed-sequence: pos (int). sequence (list). pos = (commandline num-param named "speed-sequence-position"). sequence = (commandline list-param named "speed-sequence"). commandline set-num-param named "speed-sequence-position" to (pos + 1). self set-speed-difficulty to (sequence{ (pos + 1) }). + to set-last-path-saved to filepath (string): print "Last save was in path $filepath". commandline set-string-param named "last-path-saved" to filepath. netIO set-last-path-saved to filepath. + to set-last-file-saved to file (string): print "Last save was in file $file". commandline set-string-param named "last-file-saved" to file. netIO set-last-file-saved to file. + to set-resume-file: commandline set-string-param named "resume-file" to "$file-path/$experiment-theme.txt". + to increase-stagnation-threshold: commandline set-num-param named "stagnation-threshold" to ((commandline num-param named "stagnation-threshold") + (commandline num-param named "stagnation-increment")). + to decrease-stagnation-threshold: commandline set-num-param named "stagnation-threshold" to (max(0,(commandline num-param named "stagnation-threshold") - (commandline num-param named "stagnation-increment"))). # Required for proper loading + to update-starting-innovation-counter: commandline set-num-param named "starting-innovation-number" to (ga get-innovation-counter). # Required for proper resumes + to update-end-generation: commandline set-num-param named "ending-generation" to generation. # Initialization # PENDING DELETE # input: potentially outdated input method # args: arguments to that method # - Provides backwards compatibility with old save files + to input-compatibility of input (string) with-args args (list) with-range range (list): last (string). num (int). last = input{ (|input| - 1) }. if (last == "0") || (last == "1") || (last == "2") || (last == "3") : { num = last. args = {num}. input{ (|input| - 1) } = "". print "Input of $input$num has been swapped to:". if (input == "get-close-player-impulse-of-monster-index") : input = "get-close-player-impulse-of-teammate". else if (input == "get-very-close-player-impulse-of-monster-index") : input = "get-very-close-player-impulse-of-teammate". else if (input == "get-close-to-monster-index") : input = "get-close-to-monster". else if (input == "get-very-close-to-monster-index") : input = "get-very-close-to-monster". else if (input == "get-comparative-heading-from-monster-index") : input = "get-heading-diff-to-teammate". else if (input == "get-relative-angle-to-monster-index") : input = "get-relative-angle-to-teammate". print "$input $args". } if (input == "get-signed-neg-difference-in-heading-from-heading-rear") : { print "Input of $input has been swapped to:". input = "get-heading-diff-to-teammate". print "$input". } else if (input == "get-signed-neg-angle-from-rear") : { print "Input of $input has been swapped to:". input = "get-relative-angle-to-teammate". print "$input". } else if (input == "get-signed-neg-difference-in-heading-from-player-heading-rear") : { print "Input of $input has been swapped to:". input = "get-diff-from-player-heading". print "$input". } else if (input == "get-signed-neg-angle-from-player-rear") : { print "Input of $input has been swapped to:". input = "get-angle-to-player". print "$input". } return {input, INPUT_ON, args, range}. + to get-log-object named label (string): if (label == "AveGroupPredScore") : return {"AveGroupPredScore","get-ave-group-pred-score",0.0,0.0,GOAL_OVER,(commandline num-param named "desired-pred-group-score"),0.0,LINK_OFF}. else if (label == "AvePlayerPreyScore") : return {"AvePlayerPreyScore","get-ave-player-prey-score",0.0,PLAYER_START_AVE,GOAL_NONE, (commandline num-param named "desired-prey-player-score"),0.0,LINK_OFF}. else if (label == "AveGroupFightScore") : return {"AveGroupFightScore","get-ave-group-fight-score",0.0,0.0,GOAL_OVER, (commandline num-param named "desired-fight-group-score"),0.0,LINK_OFF}. else if (label == "AvePlayerFightScore") : return {"AvePlayerFightScore","get-ave-player-fight-score",0.0,PLAYER_START_AVE,GOAL_NONE, (commandline num-param named "desired-fight-player-score"),0.0,LINK_OFF}. else if (label == "Strategy") : return {"Strategy","get-player-strategy",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF}. else if (label == "Speed") : return {"Speed","get-speed-difficulty",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF}. else if (label == "AllGoalAchievers") : return {"AllGoalAchievers","get-num-achieved-all-goals",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF}. else if (label == "AverageOutputModes") : # SMEG: Link max and min with this return {"AverageOutputModes","get-average-num-net-modes",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF}. else if (label == "TotalNodes") : return {"TotalNodes","get-total-free-nodes",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF}. else if (label == "RatioChildren") : return {"RatioChildren","get-ratio-children-in-new-pop",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF}. + to include-fitness named fitness (string) on-or-off use-objective = 1 (int): i (int). for i = 0, i < |excluded-fitnesses|, i++ : { if (fitness == excluded-fitnesses{i}) : { print "Fitness $fitness is being excluded.". return 0. } } if (fitness == "FightAssist") : push {0,0,"get-damage-assist-fitness","FightAssist",0,0,MODE_FIGHT,0.0,0.0, (commandline num-param named "desired-fight-ave-assist"), 0.0, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "FightGroup") : push {0,0,"get-group-score-fitness","FightGroup",0,0,MODE_FIGHT,0.0,0.0, (commandline num-param named "desired-fight-group-score"), 0.0, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "FightInflicted") : push {0,0,"get-damage-inflicted-fitness","FightInflicted",0,0,MODE_FIGHT,0.0,0.0, 0.0, 0.0, FITNESS_GOAL_OFF, {}, use-objective } onto fitness-info-list. else if (fitness == "PredAssist") : push {0,0,"get-damage-assist-fitness","PredAssist",0,0,MODE_PRED,0.0,0.0, (commandline num-param named "desired-pred-ave-assist"), 0.0, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "PredGroup") : push {0,0,"get-group-score-fitness","PredGroup",0,0,MODE_PRED,0.0,0.0, (commandline num-param named "desired-pred-group-score"), 0.0, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "PredInflicted") : push {0,0,"get-damage-inflicted-fitness","PredInflicted",0,0,MODE_PRED,0.0,0.0, 0.0, 0.0, FITNESS_GOAL_OFF, {}, use-objective } onto fitness-info-list. else if (fitness == "PreyReceived") : push {0,0,"get-damage-received-fitness","PreyReceived",0,0,MODE_PREY,0.0,0.0, (- (commandline num-param named "desired-prey-ave-received")), -MONSTER_START_ENERGY, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "FightReceived") : push {0,0,"get-damage-received-fitness","FightReceived",0,0,MODE_FIGHT,0.0,0.0, (- (commandline num-param named "desired-fight-ave-received")), -MONSTER_START_ENERGY, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "PreyAlive") : push {0,0,"get-iterations-alive","PreyAlive",0,0,MODE_PREY,0.0,0.0, ((commandline num-param named "desired-prey-portion-time") * (commandline num-param named "eval-iterations")), 0.0, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "FightAlive") : push {0,0,"get-iterations-alive","FightAlive",0,0,MODE_FIGHT,0.0,0.0, ((commandline num-param named "desired-fight-portion-time") * (commandline num-param named "eval-iterations")), 0.0, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "PredTimeConfined") : push {0,0,"get-iterations-confined","PredTimeConfined",0,0,MODE_PRED,0.0,0.0, ((commandline num-param named "desired-pred-portion-confined-time") * (commandline num-param named "eval-iterations")), 0.0, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "BallGoalTime") : push {0,0,"get-negative-iterations-alive","BallGoalTime",0,0,MODE_BALL,0.0,0.0, (- ((commandline num-param named "desired-ball-portion-time") * (commandline num-param named "eval-iterations"))), (- (commandline num-param named "eval-iterations")), FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "BallGoalDistance") : push {0,0,"get-goal-distance-fitness","BallGoalDistance",0,0,MODE_BALL,0.0,0.0, (- (commandline num-param named "desired-ball-goal-distance")), - LONG_DISTANCE_TO_GOAL, FITNESS_GOAL_ON, {}, use-objective } onto fitness-info-list. else if (fitness == "BehavioralDiversity") : push {0,0,"dummy-fitness","BehavioralDiversity",0,0,GAME_MODE_ALL,0.0,0.0, 0.0, 0.0, FITNESS_GOAL_OFF, {}, use-objective } onto fitness-info-list. else if (fitness == "Random") : push {0,0,"get-random-fitness","Random",0,0,GAME_MODE_ALL,0.0,0.0, 0.0, 0.0, FITNESS_GOAL_OFF, {}, use-objective } onto fitness-info-list. else { print "Unrecognized fitness: $fitness". self end-simulation. return. } + to print-details: i (int). print "". print "Log objects:". for i = 0, i < |loaded-log-objects|, i++ : { print loaded-log-objects{i}. } print "". print "Fitness:". for i = 0, i < |fitness-info-list|, i++ : { print fitness-info-list{i}{SLOT_DISPLAY_LABEL}. } print "". print "Inputs:". for i = 0, i < |additional-input-info|, i++ : { if (additional-input-info{i}{INPUT_SLOT_USE} == INPUT_ON) : { print (additional-input-info{i}{INPUT_SLOT_METHOD}), (additional-input-info{i}{INPUT_SLOT_ARGS}), (additional-input-info{i}{INPUT_SLOT_RANGE}). } } # fitness: name of valid fitness objective + to exclude-fitness named fitness (string) : push fitness onto excluded-fitnesses. print "Excluding fitness: ", excluded-fitnesses{ (|excluded-fitnesses| - 1) }. + to process-command-line-args: i (int). arg (string). key (string). hashEntry (list). tempDouble (double). tempList (list). tempInt (int). tempString (string). tempString2 (string). movieName (string). command-line-string-options (hash). command-line-numeric-options (hash). command-line-on-off-options (hash). command-line-list-options (hash). command-line-string-options = (commandline get-command-line-string-options). command-line-numeric-options = (commandline get-command-line-numeric-options). command-line-on-off-options = (commandline get-command-line-on-off-options). command-line-list-options = (commandline get-command-line-list-options). evolution-mode = new EvolutionModeArbitrator. for i = 1, i < (self get-argument-count), i++ : { arg = (self get-argument at-index i). if (arg == "h") || (arg == "help") : { print "". foreach key in keys( command-line-string-options ): { hashEntry = command-line-string-options{key}. print hashEntry{COMMAND_LINE_COMMAND},"<$key>: default =",hashEntry{COMMAND_LINE_VAL}. } print "". foreach key in keys( command-line-numeric-options ): { hashEntry = command-line-numeric-options{key}. print hashEntry{COMMAND_LINE_COMMAND},"<$key>: default =",hashEntry{COMMAND_LINE_VAL}. } print "". foreach key in keys( command-line-on-off-options ): { hashEntry = command-line-on-off-options{key}. tempDouble = hashEntry{COMMAND_LINE_VAL}. print hashEntry{COMMAND_LINE_COMMAND},":",hashEntry{COMMAND_LINE_EXPLAIN},(commandline to-on-off of tempDouble). } print "". foreach key in keys( command-line-list-options ): { hashEntry = command-line-list-options{key}. print hashEntry{COMMAND_LINE_COMMAND},"<$key>: default =",hashEntry{COMMAND_LINE_VAL}. } print "". print "l , load ". print "resume ". print "ef ". print "ls ". print "r (record a movie from the start of the simulation)". print "emode (defines evolution mode used)". print "d ". print "". self end-simulation. return. } else if (commandline num-arg named arg) : { i++. commandline assign-command-line-numeric-val of (self get-argument at-index i) to arg. } else if (commandline string-arg named arg) : { i++. commandline assign-command-line-string-val of (self get-argument at-index i) to arg. } else if (commandline bit-arg named arg) : { i++. commandline assign-command-line-on-off-val of (self get-argument at-index i) to arg. } else if (commandline list-arg named arg) : { i++. tempList = {}. tempString = (self get-argument at-index i). i++. tempString2 = (self get-argument at-index i). while tempString2 != "end" : { if tempString == "string" : { push ":$tempString2" onto tempList. } else if tempString == "int" : { tempInt = tempString2. push tempInt onto tempList. } else if tempString == "double" : { tempDouble = tempString2. push tempDouble onto tempList. } i++. tempString2 = (self get-argument at-index i). } commandline assign-command-line-list-val of tempList to arg. } else if (arg == "ef") : { i++. self exclude-fitness named (self get-argument at-index i). } else if (arg == "d") : { i++. # Write a settings file with the current default settings write-settings-and-exit = 1. settings-path = (self get-argument at-index i). i++. settings-file = (self get-argument at-index i). } else if (arg == "ls") : { # Load Settings from file i++. netIO load-settings from (self get-argument at-index i) fitnesses loaded-fitnesses inputs loaded-inputs input-args loaded-input-args input-ranges loaded-input-ranges commandline-options commandline log-objects loaded-log-objects. command-line-string-options = (commandline get-command-line-string-options). command-line-numeric-options = (commandline get-command-line-numeric-options). command-line-on-off-options = (commandline get-command-line-on-off-options). command-line-list-options = (commandline get-command-line-list-options). } else if (arg == "l") || (arg == "load") || (arg == "resume") : { load = 1. if (arg == "resume") : resume = 1. i++. inputPath = (self get-argument at-index i). self set-last-path-saved to inputPath. i++. inputFiles = (self get-argument at-index i). self set-last-file-saved to inputFiles. print "Loading $inputPath/$inputFiles". } else if (arg == "r") || (arg == "record") : { file-path = (commandline string-param named "file-path"). i++. movieName = (self get-argument at-index i). # Force the floor to display whenever recording a movie commandline assign-command-line-on-off-val of "on" to "floor". # Force the display text to be hidden whenever recording a movie commandline assign-command-line-on-off-val of "on" to "ht". print "Recording a movie". movie = new Movie. movie record to "$file-path/$movieName.mpg". } else if (arg == "emode") : { i++. evolution-mode load-evolution-mode named (self get-argument at-index i). evolution-mode load-settings using commandline. } else { print "Argument \"$arg\" not recognized". self end-simulation. return. } } commandline finish-with-commandline. + to initialize-globals: use-shaping = 0. skip-trial = 0. user-save = 0. user-end = 0. current-iteration = 0. stagnation-counter = 0. home-stretch-counter = 0. home-stretch = 0. strategy-switches = 0. deaths = 0. phase = 0. generation = 0. current-eval = 0. kills-last-gen = 0. user-increase-challenge = 0. current-population = POPULATION_PARENTS. math = new Math3D. commandline = new CommandLineHandler. triangulate = new Triangulate. triangulate give-math of math. netIO = new NetIO. excluded-fitnesses = {}. load = 0. resume = 0. overwrite-log = 0. + to determine-auto-resume-status: if (commandline bit-param named "file-output") : { # Check for auto-resume file # if it exists, set up a resume. Else, create the file and proceed normally if ((commandline string-param named "auto-resume") != "") : { print "Auto-resume on using resume file ",(commandline string-param named "auto-resume"). # Set up resume # self read-auto-resume-info. if (self file-exists named (commandline string-param named "auto-resume")) : { self read-auto-resume-info. if ((commandline string-param named "last-file-saved") != "") : { print "Last save: ", (commandline string-param named "last-file-saved"). load = 1. resume = 1. inputPath = (commandline string-param named "last-path-saved"). self set-last-path-saved to inputPath. inputFiles = (commandline string-param named "last-file-saved"). self set-last-file-saved to inputFiles. print "Auto-resuming $inputPath/$inputFiles". overwrite-log = 1. } else if ((commandline string-param named "last-file-saved") == "") : { print "Nothing to automatically resume from yet". overwrite-log = 1. } } else { # Write file and continue as normal print "Creating Resume File.". self create-auto-resume-file named (commandline string-param named "auto-resume"). } } else { print "No auto-resume". } } + to initialize-commandline-dependent-globals: tempList (list). # For backwards compatibility if (commandline num-param named "game-mode") != -1 : { if (commandline num-param named "game-mode") == MODE_COMBO : commandline set-list-param named "task-set" to ( {MODE_FIGHT,MODE_PREY,MODE_PRED} ). else if (commandline num-param named "game-mode") == MODE_LESSER_COMBO : commandline set-list-param named "task-set" to ( {MODE_PREY,MODE_PRED} ). else if (commandline num-param named "game-mode") == MODE_AGGRESSIVE_COMBO : commandline set-list-param named "task-set" to ( {MODE_FIGHT,MODE_PRED} ). else if (commandline num-param named "game-mode") == MODE_PASSIVE_COMBO : commandline set-list-param named "task-set" to ( {MODE_FIGHT,MODE_PREY} ). else commandline set-list-param named "task-set" to ( {(commandline num-param named "game-mode")} ). } player-shoots = (commandline bit-param named "player-shoots"). recency-weighted-alpha = (commandline num-param named "recency-weighted-alpha"). drop-defeated = (commandline bit-param named "lose-defeated-objectives"). file-output = (commandline bit-param named "file-output"). homogeneous = (commandline bit-param named "homogeneous"). behavior-diversity = (commandline bit-param named "use-behavior-diversity-fitness"). random-behavior-syllabus = (commandline bit-param named "random-behavior-syllabus"). stay-bound = (commandline bit-param named "stay-bound"). hide-text = (commandline bit-param named "hide-text"). file-path = (commandline string-param named "file-path"). experiment-theme = (commandline string-param named "name"). subpop-size = (commandline num-param named "subpop-size"). number-of-subpops = (commandline num-param named "number-of-subpops"). monsters-from-each-subpop = (commandline num-param named "monsters-from-each-subpop"). children-per-parent = (commandline num-param named "children-per-parent"). #current-game-mode = (commandline num-param named "game-mode"). tempList = (commandline list-param named "task-set"). current-game-mode = tempList{0}. previous-strategy = (commandline num-param named "player-strategy"). graphics = new GraphicsHandler. + to validity-check-on-population-parameters: if ((subpop-size % monsters-from-each-subpop) != 0) && (homogeneous == 0) : { print "subpop-size must be divisible by monsters-from-each-subpop.". self end-simulation. return. } if ((commandline bit-param named "keep-parents") == COMMAND_LINE_OFF) && (children-per-parent <= 1) : { print "children-per-parent must be greater than 1 if parents are not kept.". self end-simulation. return. } + to initialize-genetic-algorithm-settings: ga = new FreeNetGA. ga set-innovation-counter to (commandline num-param named "starting-innovation-number"). + to update-child-ratio-mutation-rates: rate (double). rate = 1.0 - (self get-ratio-children-in-new-pop). commandline set-num-param named "perturbation-rate" to rate. commandline set-num-param named "new-connection-rate" to rate. commandline set-num-param named "splice-rate" to rate. commandline set-num-param named "merge-nodes-rate" to rate. #commandline set-num-param named "switch-activation-rate" to rate. #commandline set-num-param named "freeze-rate" to rate. #commandline set-num-param named "new-nn-mode-rate" to rate. #commandline set-num-param named "demote-mode-rate" to rate. commandline set-num-param named "cascade-node-rate" to rate. + to initialize-tasks-list: tempList (list). i (int). tempList = (commandline list-param named "task-set"). tasks = {}. for i = 0, i < |tempList|, i++ : { # TASK_DIVERSITY_UNKNOWN is now deprecated push ( {tempList{i}, 0, TASK_DIVERSITY_UNKNOWN} ) onto tasks. } + to initialize-num-evals: num-evals = |tasks| * (commandline num-param named "start-evals"). if homogeneous : num-evals *= subpop-size. else num-evals *= (subpop-size / monsters-from-each-subpop). print "Number of evals per generation = $num-evals". self reset-shuffle-offset. + to init: i (int). j (int). k (int). log-objects (list). temp (string). temp2 (string). tempInt (int). tempList1 (list). tempList2 (list). fighting-mode (int). predation (int). as-prey (int). with-ball (int). unit-test (object). shaping-fitnesses (list). #tempVector (vector). print "########### New Simulation Run ###########". write-settings-and-exit = 0. settings-file = "". settings-path = "". # Save memory self disable-freed-instance-protection. self initialize-globals. loaded-log-objects = {}. loaded-fitnesses = {}. loaded-inputs = {}. loaded-input-args = {}. loaded-input-ranges = {}. self process-command-line-args. if (commandline bit-param named "unit-tests") : { print "UNIT TESTS". print "--------------------------------------------". unit-test = new UnitTest. unit-test test-subset. unit-test test-set-equal. unit-test test-compare. unit-test test-compare-with-error. unit-test test-angle-difference. unit-test test-mode-counts. unit-test test-mode-arbitrator. unit-test test-mode-mutation. unit-test test-nsga2. print "--------------------------------------------". self end-simulation. } self determine-auto-resume-status. # load from file if load == 1 : { loaded-log-objects = {}. loaded-fitnesses = {}. loaded-inputs = {}. loaded-input-args = {}. loaded-input-ranges = {}. netIO load-settings from "$inputPath/$inputFiles" fitnesses loaded-fitnesses inputs loaded-inputs input-args loaded-input-args input-ranges loaded-input-ranges commandline-options commandline log-objects loaded-log-objects. print "". # command line should override file settings, unless resuming if (resume == 0) : self process-command-line-args. } self initialize-commandline-dependent-globals. self validity-check-on-population-parameters. self initialize-genetic-algorithm-settings. # End command line arguments # Augment output file name if drop-defeated : experiment-theme = "-LoseDefeated$experiment-theme". if (commandline bit-param named "random-sampling") : experiment-theme = "-RandomSample$experiment-theme". if (commandline bit-param named "use-z-scores") : experiment-theme = "-Z$experiment-theme". if (commandline bit-param named "max-dominate-selection") : experiment-theme = "-MaxD$experiment-theme". if stay-bound : experiment-theme = "-Bound$experiment-theme". self initialize-tasks-list. for i = 0, i < |tasks|, i++ : { if (tasks{i}{TASK_SLOT_TASK} == MODE_FIGHT) : experiment-theme = "Fight$experiment-theme". else if (tasks{i}{TASK_SLOT_TASK} == MODE_PRED) : experiment-theme = "Pred$experiment-theme". else if (tasks{i}{TASK_SLOT_TASK} == MODE_PREY) : experiment-theme = "Prey$experiment-theme". else if (tasks{i}{TASK_SLOT_TASK} == MODE_BALL) : experiment-theme = "Ball$experiment-theme". } # Starting network type if (load == 1) && (resume == 0) : temp = "-Load". else if (commandline bit-param named "fs-net") : temp = "-Blank". else temp = "-Full". experiment-theme = "$experiment-theme$temp". temp = "". if (commandline bit-param named "use-z-scores") : selection = new ZScoresGA. else if (commandline bit-param named "max-dominate-selection") : selection = new MaxDominate. else { selection = new NSGA2. tempInt = (commandline num-param named "last-front"). selection set-last-front-selection to tempInt. if (commandline num-param named "alpha-dominance") > 0.0 : selection set-alpha to (commandline num-param named "alpha-dominance"). if (tempInt == LAST_FRONT_RANDOM) : experiment-theme = "Random-$experiment-theme". else if (tempInt == LAST_FRONT_CROWDING_DISTANCE) : experiment-theme = "CrowdingDistance-$experiment-theme". else if (tempInt == LAST_FRONT_RANK_OBJECTIVES) : experiment-theme = "Rank-$experiment-theme". else { print "Did not recognize selection type: $tempInt". self end-simulation. return. } } selection set-generation to (commandline num-param named "ending-generation"). if (resume == 1) : { print "Drop name $experiment-theme due to resume". experiment-theme = (commandline string-param named "experiment-theme"). experiment-theme = "R-$experiment-theme". print "Go with $experiment-theme instead". } else if (evolution-mode ask-has-mode) : { temp = evolution-mode get-name. temp2 = "-". experiment-theme = "$temp$temp2$experiment-theme". } temp = "". temp2 = "". commandline set-string-param named "experiment-theme" to experiment-theme. free evolution-mode. # Game mode self initialize-num-evals. tempInt = subpop-size * number-of-subpops. print "Num unique brains per population = $tempInt". # Create the environment. # 0 and 1 result in the same run. Adding 1 offsets this self set-random-seed to ((commandline num-param named "random-seed") + 1 + (commandline num-param named "random-seed-offset")). if (commandline bit-param named "use-walls") : self make-walls. if (commandline bit-param named "use-power-ups") : self place-powerups. triangulate fill-theta-starts with-sub-pops number-of-subpops monsters-per-sub monsters-from-each-subpop. # Create the Player. self spawn-player. # Setup GA self zero-scores. # The initial change to game mode will set this to 0 current-population-num = subpop-size - 1. fighting-mode = 0. predation = 0. as-prey = 0. with-ball = 0. for i = 0, i < |tasks|, i++ : { if (tasks{i}{TASK_SLOT_TASK} == MODE_FIGHT) : fighting-mode = 1. else if (tasks{i}{TASK_SLOT_TASK} == MODE_PRED) : predation = 1. else if (tasks{i}{TASK_SLOT_TASK} == MODE_PREY) : as-prey = 1. else if (tasks{i}{TASK_SLOT_TASK} == MODE_BALL) : with-ball = 1. } # Set fitness objectives fitness-info-list = {}. shaping-fitnesses = (commandline string-list-param named "fitness-shaping"). if |shaping-fitnesses| > 0 : { use-shaping = 1. print "". print "Shaping on fitness objectives.". for i = 0, i < |shaping-fitnesses|, i++ : { if (shaping-fitnesses{i} == "BehavioralDiversity") : diversity-fitness-index = |fitness-info-list|. self include-fitness named shaping-fitnesses{i}. if (i <= (commandline num-param named "index-of-last-shaping-objective-added")) : fitness-info-list{i}{SLOT_USE_OBJECTIVE} = FITNESS_OBJECTIVE_ON. else fitness-info-list{i}{SLOT_USE_OBJECTIVE} = FITNESS_OBJECTIVE_OFF. } } else if |loaded-fitnesses| > 0 : { # Backwards compatibility checks if (commandline num-param named "desired-pred-ave-confined-time") > 0 : commandline set-num-param named "desired-pred-portion-confined-time" to ((commandline num-param named "desired-pred-ave-confined-time") / (commandline num-param named "eval-iterations")). if (commandline num-param named "desired-fight-ave-time") > 0 : commandline set-num-param named "desired-fight-portion-time" to ((commandline num-param named "desired-fight-ave-time") / (commandline num-param named "eval-iterations")). if (commandline num-param named "desired-prey-ave-time") > 0 : commandline set-num-param named "desired-prey-portion-time" to ((commandline num-param named "desired-prey-ave-time") / (commandline num-param named "eval-iterations")). if (commandline num-param named "desired-ball-ave-time") > 0 : commandline set-num-param named "desired-ball-portion-time" to ((commandline num-param named "desired-ball-ave-time") / (commandline num-param named "eval-iterations")). print "". print "Loading fitnesses from save file.". for i = 0, i < |loaded-fitnesses|, i++ : { if (loaded-fitnesses{i}{LOAD_FITNESS_LABEL} == "BehavioralDiversity") : diversity-fitness-index = |fitness-info-list|. self include-fitness named (loaded-fitnesses{i}{LOAD_FITNESS_LABEL}) on-or-off (loaded-fitnesses{i}{LOAD_FITNESS_USE_OBJECTIVE}). } } else { if fighting-mode : { (self include-fitness named "FightAssist"). (self include-fitness named "FightGroup"). (self include-fitness named "FightInflicted"). } if predation : { (self include-fitness named "PredAssist"). (self include-fitness named "PredGroup"). (self include-fitness named "PredInflicted"). } if as-prey : (self include-fitness named "PreyReceived"). if fighting-mode : (self include-fitness named "FightReceived"). if predation && stay-bound && (commandline bit-param named "use-pred-confined-time") : (self include-fitness named "PredTimeConfined"). if as-prey : (self include-fitness named "PreyAlive"). if fighting-mode : (self include-fitness named "FightAlive"). if with-ball : { (self include-fitness named "BallGoalTime"). (self include-fitness named "BallGoalDistance"). } if (commandline bit-param named "random-fitness") : self include-fitness named "Random". if behavior-diversity : { diversity-fitness-index = |fitness-info-list|. self include-fitness named "BehavioralDiversity". } } # Reclaim space free excluded-fitnesses. excluded-fitnesses = {}. self reset-fitness-averages. if (resume == 1): # Remember previous averages { tempList1 = commandline list-param named "previous-fitness-average-averages". print "tempList1=", tempList1. tempList2 = commandline list-param named "previous-fitness-best-averages". print "tempList2=", tempList2. for i = 0, i < |fitness-info-list|, i++ : { fitness-info-list{i}{SLOT_CURRENT_AVE_AVE} = tempList1{i}. fitness-info-list{i}{SLOT_BEST_AVE} = tempList2{i}. } } if behavior-diversity || (commandline bit-param named "restrict-similar-modes") : { behavior-state = new BehaviorState. behavior-state give-commandline this commandline. } self blank-current-fitnesses. # Set up monsters additional-input-info = {}. if |loaded-inputs| > 0 : { print "". print "Loading inputs from save file.". for i = 0, i < |loaded-inputs|, i++ : { # Backwards compatibility if (i >= |loaded-input-args|) : push {} onto loaded-input-args. if (i >= |loaded-input-ranges|) : push {} onto loaded-input-ranges. push (self input-compatibility of (loaded-inputs{i}) with-args (loaded-input-args{i}) with-range (loaded-input-ranges{i})) onto additional-input-info. } } else { if ((commandline bit-param named "sensor-array-only") == COMMAND_LINE_OFF) : { if ((commandline bit-param named "bias-senses") == 1) : push {"get-bias",INPUT_ON,{},{}} onto additional-input-info. push {"get-diff-from-player-heading",INPUT_ON,{},{PI}} onto additional-input-info. push {"get-angle-to-player",INPUT_ON,{},{PI}} onto additional-input-info. if with-ball : { push {"get-angle-to-goal",INPUT_ON,{},{PI}} onto additional-input-info. push {"get-angle-difference-between-ball-and-goal",INPUT_ON,{},{PI}} onto additional-input-info. push {"get-comparative-goal-player-distance",INPUT_ON,{},{LONG_DISTANCE_TO_GOAL}} onto additional-input-info. } if (fighting-mode == 1 || as-prey == 1) : push {"get-yelp-of-pain",INPUT_ON,{},{}} onto additional-input-info. if (fighting-mode == 1 || predation == 1) : push {"get-shout-of-encouragement",INPUT_ON,{},{}} onto additional-input-info. if (fighting-mode == 1 || predation == 1) : push {"is-player-locked",INPUT_ON,{},{}} onto additional-input-info. if ((commandline bit-param named "close-player-senses") == 1) : { push {"get-close-player-impulse",INPUT_ON,{},{}} onto additional-input-info. push {"get-very-close-player-impulse",INPUT_ON,{},{}} onto additional-input-info. } if (commandline bit-param named "anyone-close-senses") : { # smeg: add close senses for the goal push {"get-anyone-close-to-player",INPUT_ON,{},{}} onto additional-input-info. push {"get-anyone-very-close-to-player",INPUT_ON,{},{}} onto additional-input-info. } push {"in-front-of-player",INPUT_ON,{},{}} onto additional-input-info. if ((commandline bit-param named "personal-awareness") && (fighting-mode == 1 || as-prey == 1)) : push {"get-just-hit",INPUT_ON,{},{}} onto additional-input-info. if ((commandline bit-param named "personal-awareness") && (fighting-mode == 1 || predation == 1)) : push {"get-just-ate",INPUT_ON,{},{}} onto additional-input-info. if (fighting-mode == 1) : push {"get-close-sword-impulse",INPUT_ON,{},{}} onto additional-input-info. if (fighting-mode == 1) : push {"get-very-close-sword-impulse",INPUT_ON,{},{}} onto additional-input-info. # Rarely used if ((commandline bit-param named "facing-senses") == 1) : { push {"get-facing-player",INPUT_ON,{},{}} onto additional-input-info. push {"get-player-facing-me",INPUT_ON,{},{}} onto additional-input-info. } if ((commandline bit-param named "distance-senses") == 1) : { push {"get-delta-player-distance",INPUT_ON,{},{MIN_GOAL_BUFFER}} onto additional-input-info. push {"get-distance-from-player",INPUT_ON,{},{LONG_DISTANCE_TO_GOAL}} onto additional-input-info. } if MONSTERS_INTERACT : push {"get-just-bumped",INPUT_ON,{},{}} onto additional-input-info. if MONSTERS_INTERACT || (commandline bit-param named "teamwork") : { push {"get-close-monster-impulse",INPUT_ON,{},{}} onto additional-input-info. push {"get-very-close-monster-impulse",INPUT_ON,{},{}} onto additional-input-info. push {"get-right-side-monster-impulse",INPUT_ON,{},{}} onto additional-input-info. push {"get-left-side-monster-impulse",INPUT_ON,{},{}} onto additional-input-info. } #push {"flanking-player",INPUT_ON,{},{}} onto additional-input-info. #if (commandline bit-param named "personal-awareness") : push {"get-energy",INPUT_ON,{},{MONSTER_START_ENERGY}} onto additional-input-info. # Communication if (commandline bit-param named "index-based-senses") : { for i = 0, i < (number-of-subpops * monsters-from-each-subpop), i++ : { push {"get-heading-diff-to-teammate",INPUT_ON,{i},{PI}} onto additional-input-info. push {"get-relative-angle-to-teammate",INPUT_ON,{i},{PI}} onto additional-input-info. push {"get-teammate-just-ate",INPUT_ON,{i},{}} onto additional-input-info. #smeg: consider using these again #push {"get-close-to-monster",INPUT_ON,{i},{}} onto additional-input-info. #push {"get-very-close-to-monster",INPUT_ON,{i},{}} onto additional-input-info. #push {"get-close-player-impulse-of-teammate",INPUT_ON,{i},{}} onto additional-input-info. #push {"get-very-close-player-impulse-of-teammate",INPUT_ON,{i},{}} onto additional-input-info. } } if (commandline bit-param named "use-walls") : push {"get-facing-x",INPUT_ON,{},{}} onto additional-input-info. if (commandline bit-param named "use-walls") : push {"get-facing-z",INPUT_ON,{},{}} onto additional-input-info. if (commandline bit-param named "use-walls") : push {"facing-wall",INPUT_ON,{},{}} onto additional-input-info. if (commandline bit-param named "use-walls") : push {"back-to-wall",INPUT_ON,{},{}} onto additional-input-info. if (commandline bit-param named "use-walls") : push {"get-just-hit-wall",INPUT_ON,{},{}} onto additional-input-info. } if (commandline bit-param named "use-walls") : { for i = 0, i < (commandline num-param named "sensor-array-size"), i++ : { push {"get-wall-sensor",INPUT_ON,{i},{}} onto additional-input-info. } } if player-shoots : { push {"get-angle-nearest-bullet",INPUT_ON,{},{}} onto additional-input-info. for i = 0, i < (commandline num-param named "sensor-array-size"), i++ : { push {"get-bullet-sensor",INPUT_ON,{i},{}} onto additional-input-info. } } for i = 0, i < (commandline num-param named "sensor-array-size"), i++ : { push {"get-player-sensor",INPUT_ON,{i},{}} onto additional-input-info. } for i = 0, i < (commandline num-param named "sensor-array-size"), i++ : { push {"get-monster-sensor",INPUT_ON,{i},{}} onto additional-input-info. } if (fighting-mode == 1) && (commandline bit-param named "stick-sensors") : { for i = 0, i < (commandline num-param named "sensor-array-size"), i++ : { push {"get-sword-sensor",INPUT_ON,{i},{}} onto additional-input-info. } } } if random-behavior-syllabus : { # Initialize syllabus behavior-state randomize-syllabus length (self get-num-inputs). } if (write-settings-and-exit == 1) : { netIO set-file-path to settings-path. netIO write-save-file with-identifier settings-file commandline-options commandline fitnesses fitness-info-list inputs additional-input-info logs log. print "Wrote settings to file $settings-path/$settings-file.save". self end-simulation. } else { if (load != 1) : { # 3 outputs for forward/backward movement and 3 for turning if (commandline bit-param named "action-selector-net") : { commandline set-num-param named "num-output-neurons" to OUTPUTS_ACTION_SELECTOR. } if (commandline bit-param named "predefined-network-modes") : { commandline set-num-param named "num-output-neurons" to ((commandline num-param named "num-output-neurons")*|tasks|). } else if (commandline num-param named "num-network-modes") > 1 : { commandline set-num-param named "num-output-neurons" to (((commandline num-param named "num-output-neurons") + 1) * (commandline num-param named "num-network-modes")). } } monster-starting-weights = {}. for i = 0, i < |additional-input-info|, i++ : { tempList1 = {}. for j = 0, j < (commandline num-param named "num-output-neurons"), j++ : { push 0 onto tempList1. } push tempList1 onto monster-starting-weights. } # for outputs for i = 0, i < (commandline num-param named "num-output-neurons"), i++ : { push {} onto monster-starting-weights. } if (number-of-subpops * monsters-from-each-subpop) > 1 : monsters = (number-of-subpops * monsters-from-each-subpop) new Monster. else monsters = {new Monster}. mode-arbitrator = new ModeArbitrator. mode-arbitrator set-params command commandline. parent-brains = {}. child-brains = {}. type-trials-for-brains = {}. for i = 0, i < number-of-subpops, i++ : { push {} onto type-trials-for-brains. push {} onto parent-brains. push {} onto child-brains. for j = 0, j < subpop-size, j++ : { # the four 0s correspond to the 4 possible modes so far: Fight, Pred, Prey, Ball push {0,0,0,0} onto (type-trials-for-brains{i}). push (self new-starting-brain) onto (parent-brains{i}). for k = 0, k < children-per-parent, k++ : push {} onto (child-brains{i}). } } self give-monsters-starting-brains from parent-brains. # Reclaim space free monster-starting-weights. monster-starting-weights = {}. # Load Population if load == 1 : (self load-population from-path inputPath files inputFiles type "children"). # Prepare log log-objects = {}. if (|loaded-log-objects| > 0) : { for i = 0, i < |loaded-log-objects|, i++ : { print loaded-log-objects{i}. push (self get-log-object named (loaded-log-objects{i})) onto log-objects. } } else { if (predation == 1) : push (self get-log-object named "AveGroupPredScore") onto log-objects. if (as-prey == 1) : push (self get-log-object named "AvePlayerPreyScore") onto log-objects. if (fighting-mode == 1) : push (self get-log-object named "AveGroupFightScore") onto log-objects. if (fighting-mode == 1) : push (self get-log-object named "AvePlayerFightScore") onto log-objects. if (commandline bit-param named "task-progression") : push (self get-log-object named "Strategy") onto log-objects. else push (self get-log-object named "Speed") onto log-objects. push (self get-log-object named "AllGoalAchievers") onto log-objects. # SMEG: Link max and min with this push (self get-log-object named "AverageOutputModes") onto log-objects. push (self get-log-object named "TotalNodes") onto log-objects. push (self get-log-object named "RatioChildren") onto log-objects. } #if (predation == 1) : # push {"AveGroupPredScore","get-ave-group-pred-score",0.0,0.0,GOAL_OVER, # (commandline num-param named "desired-pred-group-score"),0.0,LINK_OFF} onto log-objects. #if (as-prey == 1) : # push {"AvePlayerPreyScore","get-ave-player-prey-score",0.0,PLAYER_START_AVE,GOAL_NONE, # (commandline num-param named "desired-prey-player-score"),0.0,LINK_OFF} onto log-objects. #if (fighting-mode == 1) : # push {"AveGroupFightScore","get-ave-group-fight-score",0.0,0.0,GOAL_OVER, # (commandline num-param named "desired-fight-group-score"),0.0,LINK_OFF} onto log-objects. #if (fighting-mode == 1) : # push {"AvePlayerFightScore","get-ave-player-fight-score",0.0,PLAYER_START_AVE,GOAL_NONE, # (commandline num-param named "desired-fight-player-score"),0.0,LINK_OFF} onto log-objects. # #if (commandline bit-param named "task-progression") : # push {"Strategy","get-player-strategy",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF} onto log-objects. #else # push {"Speed","get-speed-difficulty",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF} onto log-objects. # #push {"AllGoalAchievers","get-num-achieved-all-goals",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF} onto log-objects. # # SMEG: Link max and min with this #push {"AverageOutputModes","get-average-num-net-modes",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF} onto log-objects. # #push {"TotalNodes","get-total-free-nodes",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF} onto log-objects. # #push {"RatioChildren","get-ratio-children-in-new-pop",0.0,0.0,GOAL_NONE,0,0.0,LINK_OFF} onto log-objects. log = new Log. log set-path to file-path. netIO set-file-path to file-path. log assign-log-list of log-objects. if file-output : { while (log log-file-exists with-file "$file-path/$experiment-theme.txt") && !overwrite-log : { print "$file-path/$experiment-theme.txt already exists". if resume : { experiment-theme = "Resume-$experiment-theme". print "Changing theme to $experiment-theme". } else { print "Log file already exists: $file-path/$experiment-theme.txt : terminating simulation". controller end-simulation. return. } } if overwrite-log : { print "Overwriting log because there was no useful info yet". } log write-headers using fitness-info-list to-file experiment-theme. } if (resume == 1): { log copy-previous-file named (commandline string-param named "resume-file") to-file experiment-theme. print "Resuming previous experiment". if (commandline bit-param named "progress-on-resume") : { self increase-challenge. print "Increasing the challenge". commandline set-bit-param named "progress-on-resume" to COMMAND_LINE_OFF. } } # Overwrite resume-file after copying over or set for first time self set-resume-file. log reset-log-averages. if ((load == 0) || (resume == 1)) && (commandline bit-param named "task-progression") : self set-speed-difficulty to 1.0. # Start game self move-light to (0, 1000, 0). self set-display-text-scale to 0.4. self print-details. current-game-mode-counter = 0. self switch-current-game-mode. if (commandline bit-param named "HUD") : { myHUD = new HUD. myHUD set-fov with-width (commandline num-param named "hud-dimension") with-height (commandline num-param named "hud-dimension") at-orgin-x 1 at-orgin-y 1 at-distance 4. if (commandline bit-param named "focus-on-network-view") : { myHUD set-location to (0, 0, 0). myHUD set-viewdistance to VIEW_DISTANCE. myHUD track-object from (0, 10, -10). } else { myHUD set-location to (0,VIEW_HEIGHT,0). myHUD set-viewdistance to VIEW_DISTANCE. myHUD track-object. } } if (commandline bit-param named "focus-on-network-view") || (commandline bit-param named "HUD") : { view = new NetViewer. self draw-net net (monsters{0} extract-genome). } free loaded-log-objects. free loaded-fitnesses. free loaded-inputs. free loaded-input-args. free loaded-input-ranges. loaded-log-objects = {}. loaded-fitnesses = {}. loaded-inputs = {}. loaded-input-args = {}. loaded-input-ranges = {}. #smeg: temp hack #commandline set-num-param named "gens-between-write" to 10. #smeg temp test: #for i = 0, i < |parent-brains{0}|, i++ : #{ # for j = i + 1, j < |parent-brains{0}|, j++ : # { # tempVector = (ga measure-genetic-difference between (parent-brains{0}{i}) and-net (parent-brains{0}{j})). # print "Compare $i and $j : $tempVector". # } #} } + to get-current-game-mode-counter: #print "mode:",current-game-mode. #print "mode-counter:",current-game-mode-counter. if (current-game-mode-counter == 0) : return (|tasks| - 1). else return (current-game-mode-counter - 1). + to get-real-num-evals: if current-population == POPULATION_PARENTS : return num-evals. else return (num-evals * children-per-parent). # Maintains simulation display + to iterate: i (int). life (int). message-best (string). message-worst (string). tempInt (int). temp (string). groupInt (int). playerInt (int). extra-stats (string). real-num-evals (int). current-iteration++. self update-neighbors. if !hide-text : { groupInt = group-score. playerInt = player-score. if player: life = (player get-energy). generation = selection get-generation. if player: self set-display-text number 0 to "Life: $life Deaths: $deaths PlayerScore: [$playerInt][$ave-player-score] GroupScore: [$groupInt][$ave-group-score]" at-x -0.2 at-y -.9. if current-population == POPULATION_PARENTS : temp = "Parents". else if current-population == POPULATION_CHILDREN : temp = "Children". extra-stats = "Population: $temp ($current-population-num) Stagnation: $stagnation-counter". real-num-evals = (self get-real-num-evals). self set-display-text number 1 to "Eval: $current-eval/$real-num-evals $extra-stats Generation: $generation Kills: $kills-last-gen Iteration: $current-iteration" at-x -0.2 at-y -.95. message-best = "". message-worst = "". for i=0, i<|fitness-info-list|, i++ : { temp = fitness-info-list{i}{SLOT_DISPLAY_LABEL}. if (fitness-info-list{i}{SLOT_USE_OBJECTIVE} == FITNESS_OBJECTIVE_OFF) : temp = "OFF:$temp". message-best = "$message-best$temp: ". message-worst = "$message-worst$temp: ". tempInt = fitness-info-list{i}{SLOT_CURRENT_BEST_FITNESS}. message-best = "$message-best$tempInt ". tempInt = fitness-info-list{i}{SLOT_CURRENT_WORST_FITNESS}. message-worst = "$message-worst$tempInt ". } self set-display-text number 4 to "Best: $message-best" at-x -.95 at-y .95. self set-display-text number 5 to "Worst: $message-worst" at-x -.95 at-y .90. if user-save == 1: self set-display-text number 6 to "User Save" at-x -.95 at-y .85. else self set-display-text number 6 to "" at-x -.95 at-y .85. } super iterate. if (current-iteration > (commandline num-param named "eval-iterations")) || (skip-trial == 1) || (self all-monsters-dead) || ((current-game-mode == MODE_BALL) && goal && (goal goal-sunk)) || (stay-bound && (current-game-mode == MODE_PRED) && !(self player-is-surrounded)) : { skip-trial = 0. self end-eval. } # Stats + to zero-scores: ave-group-score = 0.0. group-score = 0.0. ave-player-score = 0.0. player-score = 0.0. player-powerups = 0. ave-group-fight-score = 0.0. ave-group-pred-score = 0.0. ave-player-fight-score = 0.0. ave-player-prey-score = 0.0. num-achieved-all-goals = 0. self zero-trials. + to zero-trials: i (int). j (int). k (int). reps (int). reps = 1. if current-population == POPULATION_CHILDREN : reps = children-per-parent. # the four 0s correspond to the 4 possible modes so far: Fight, Pred, Prey, Ball type-trials = {0,0,0,0}. type-trials-for-brains = {}. for i = 0, i < number-of-subpops, i++ : { push {} onto type-trials-for-brains. for j = 0, j < subpop-size, j++ : { for k = 0, k < reps, k++ : # the four 0s correspond to the 4 possible modes so far: Fight, Pred, Prey, Ball push {0,0,0,0} onto (type-trials-for-brains{i}). } } # Returns list of size s1, where each index contains a list # consisting of (s2 * s3) empty lists. + to list-of-blanks size1 s1 (int) size2 s2 (int) size3 s3 (int): blanks (list). i (int). j (int). k (int). blanks = {}. for i = 0, i < s1, i++ : { push {} onto blanks. for j = 0, j < s2, j++ : { for k = 0, k < s3, k++ : push {} onto (blanks{i}). } } return blanks. + to blank-current-fitnesses: #i (int). #j (int). #k (int). reps (int). reps = 1. if current-population == POPULATION_CHILDREN : reps = children-per-parent. free current-fitnesses. current-fitnesses = (self list-of-blanks size1 number-of-subpops size2 subpop-size size3 reps). #current-fitnesses = {}. #for i = 0, i < number-of-subpops, i++ : #{ # # New sub-population # push {} onto current-fitnesses. # # New individuals within sub-population # for j = 0, j < subpop-size, j++ : # { # for k = 0, k < reps, k++ : push {} onto (current-fitnesses{i}). # } #} if (commandline bit-param named "track-mode-usage") : { free current-mode-usage. current-mode-usage = (self list-of-blanks size1 number-of-subpops size2 subpop-size size3 reps). } if behavior-diversity : { free current-behavior-vectors. current-behavior-vectors = (self list-of-blanks size1 number-of-subpops size2 subpop-size size3 reps). #current-behavior-vectors = {}. #for i = 0, i < number-of-subpops, i++ : #{ # # New sub-population # push {} onto current-behavior-vectors. # # New individuals within sub-population # for j = 0, j < subpop-size, j++ : # { # for k = 0, k < reps, k++ : # { # push {} onto (current-behavior-vectors{i}). # } # } #} } + to get-num-achieved-all-goals: return num-achieved-all-goals. + to get-group-score: return group-score. + to get-ave-group-score: return ave-group-score. + to get-ave-group-fight-score: return ave-group-fight-score. + to get-ave-group-pred-score: return ave-group-pred-score. + to get-ave-player-score: return ave-player-score. + to get-ave-player-fight-score: return ave-player-fight-score. + to get-ratio-children-in-new-pop: return ratio-children-in-new-pop. + to get-ave-player-prey-score: return ave-player-prey-score. + to get-player-strategy: return (commandline num-param named "player-strategy"). + to set-player-strategy to strat (int): commandline set-num-param named "player-strategy" to strat. + to get-total-free-nodes: return |(all FreeNode)|. + to get-average-num-net-modes: tempList (list). i (int). sum (double). sum = 0. tempList = (all FreeNetwork). for i = 0, i < |tempList|, i++ : { sum += (mode-arbitrator get-num-output-modes-from-net network (tempList{i})). } return (sum / ( |tempList| )). # Game Mode + to get-current-game-mode: return current-game-mode. # pos: index within subpopulation # - pos < |brains{i}| for all i + to replace-monsters from pos (int): i (int). j (int). monster-index (int). pop-slot (int). brains (list). random-offset (int). random-offset = 0. if current-population == POPULATION_PARENTS : brains = parent-brains. else if current-population == POPULATION_CHILDREN : brains = child-brains. for i = 0, i < number-of-subpops, i++ : { for j = 0, j < monsters-from-each-subpop, j++ : { monster-index = (i * monsters-from-each-subpop) + j. if homogeneous : pop-slot = pos. else { if (commandline bit-param named "random-sampling") && (shuffle-offset > 0) : random-offset = random[ (|brains{i}| - 1) ]. pop-slot = (pos + shuffle-offset + random-offset + j) % |brains{i}|. } monsters{ monster-index } replace-brain with-genome (brains{i}{pop-slot}). monsters{ monster-index } assign-subpop-index of i. monsters{ monster-index } set-population-slot to pop-slot. monsters{ monster-index } remember-index of monster-index. } } if myHUD || (commandline bit-param named "focus-on-network-view") : { self draw-net net (monsters{0} extract-genome). } + to switch-current-game-mode: #new-color (vector). #i (int). reps (int). trials-so-far (int). reps = 1. if current-population == POPULATION_CHILDREN : reps = children-per-parent. if (current-game-mode-counter == 0) : { if homogeneous : { trials-so-far = type-trials-for-brains{0}{current-population-num}{ (tasks{ current-game-mode-counter }{TASK_SLOT_TASK}) }. # Give each homogeneous team all of its evaluations before switching it # Subpop 0 is used because a homogeneous team should only have one subpop if (trials-so-far == 0) || ((trials-so-far / monsters-from-each-subpop) == (commandline num-param named "start-evals")) : { current-population-num++. current-population-num %= (subpop-size * reps). self replace-monsters from current-population-num. } } else { current-population-num++. current-population-num %= ((subpop-size * reps) / monsters-from-each-subpop). if (current-population-num == 0) : shuffle-offset = (shuffle-offset + SHUFFLE_JUMP) % subpop-size. self replace-monsters from (current-population-num * monsters-from-each-subpop). } } current-game-mode = tasks{ current-game-mode-counter }{TASK_SLOT_TASK}. current-game-mode-counter = (current-game-mode-counter + 1) % |tasks|. #new-color = (self get-bot-color). #for i = 0, i < |monsters|, i++ : monsters{i} set-color to new-color. # Write Networks + to catch-key-s-down: user-save = 1. + to catch-key-i-down: user-increase-challenge = 1. + to catch-key-n-down: skip-trial = 1. + to write-networks with-identifier name (string): i (int). currentAveAves (list). currentBestAves (list). # Update fitness averages currentAveAves = {}. currentBestAves = {}. for i = 0, i < |fitness-info-list|, i++ : { push (fitness-info-list{i}{SLOT_CURRENT_AVE_AVE}) onto currentAveAves. push (fitness-info-list{i}{SLOT_BEST_AVE}) onto currentBestAves. } commandline set-list-param named "previous-fitness-average-averages" to currentAveAves. commandline set-list-param named "previous-fitness-best-averages" to currentBestAves. netIO write-networks with-identifier name commandline-options commandline fitnesses fitness-info-list inputs additional-input-info parent-fitness-list parent-fitnesses child-fitness-list child-fitnesses children child-brains logs log. commandline set-bit-param named "progress-on-resume" to COMMAND_LINE_OFF. if ((commandline string-param named "auto-resume") != "") : self create-auto-resume-file named (commandline string-param named "auto-resume"). # Call when population is stagnating + to load-last-save: last-file-saved (string). last-path-saved (string). last-file-saved = netIO get-last-file-saved. last-path-saved = netIO get-last-path-saved. if (last-file-saved != "") : { (self load-population from-path last-path-saved files last-file-saved type "children"). } self log-to-file text "#$experiment-theme - Stagnation Reset, loading: $last-path-saved/$last-file-saved". + to log-to-file text s (string): log log-to-file text s to-file experiment-theme. # filePath: directory with files # fileSet: name of files to load # group: "parents" or "children" (group to load) + to load-population from-path filePath (string) files fileSet (string) type group (string): netIO load-population from-path filePath files fileSet type group subpops number-of-subpops sub-size subpop-size parent-list parent-brains. self give-monsters-starting-brains from parent-brains. + to catch-key-e-down: user-end = 1. print "User requests to terminate simulation". # Player movement control + to catch-key-up-down: if !(player is-locked): player set-forward-coeff to ((commandline num-param named "speed-difficulty") * PLAYER_WALK_SPEED). + to catch-key-up-up: if !(player is-locked): player set-forward-coeff to 0. + to catch-key-down-down: if !(player is-locked): player set-forward-coeff to (-PLAYER_WALK_SPEED * (commandline num-param named "speed-difficulty")). + to catch-key-down-up: if !(player is-locked): player set-forward-coeff to 0. + to catch-key-left-down: if !(player is-locked): player set-turn-angle to (-PLAYER_TURN_SPEED). + to catch-key-left-up: if !(player is-locked): player set-turn-angle to 0. + to catch-key-right-down: if !(player is-locked): player set-turn-angle to PLAYER_TURN_SPEED. + to catch-key-right-up: if !(player is-locked): player set-turn-angle to 0. # space bar #+ to catch-key-0x20-down: + to catch-key-z-down: if !(player is-locked): { if player-shoots : { if (player is-armed) : player attack. else player fire. } else { if (player is-armed) : player fire. else player attack. } } # Strategy Switch + to reset-strategy: log reset-log-averages. self reset-fitness-averages. player set-forward-coeff to 0. player set-turn-angle to 0. # num: valid strategy constant + to switch-strategy to num (int): stagnation-counter = 0. self reset-strategy. previous-strategy = (self get-player-strategy). self set-player-strategy to num. # Player Info + to anyone-close-to-player: shortest-distance (double). shortest-distance = (triangulate get-distance-to-nearest-object from (player get-location) given monsters). if (shortest-distance < (commandline num-param named "very-close-player")) : return 1. return 0. + to anyone-very-close-to-player: shortest-distance (double). shortest-distance = (triangulate get-distance-to-nearest-object from (player get-location) given monsters). if (shortest-distance < ((commandline num-param named "very-close-player") / 2)) : return 1. return 0. + to anyone-in-front-of-player: i (int). for i=0, i<|monsters|, i++ : { if (monsters{i} in-front-of-player) : return 1. } return 0. + to player-is-swinging: return (player swinging). + to spawn-player: i (int). bullets (list). t (double). r (double). x (double). z (double). if goal: free goal. if player : { player free-sword. free player. } player = new Player. player move to (0, 1, 0). if current-game-mode == MODE_BALL : { r = MIN_GOAL_BUFFER + ((commandline num-param named "speed-difficulty") * (commandline num-param named "goal-distance")). t = random[(2 * PI)]. x = r * cos(t). z = r * sin(t). goal = new Goal. goal create at (x, 0.0, z). } if (commandline bit-param named "random-player-orientation") : player point vertex (0, 1, 0) at (math get-random-unit-vector). else player point vertex (0, 1, 0) at (1,0,0). bullets = all Bullet. for i = 0, i < |bullets|, i++ : { bullets{i} disappear after-hitting self. } for i = 0, i < |monsters|, i++ : { if (monsters{i} get-deaths) == 0 : monsters{i} new-placement. } if (commandline bit-param named "focus-on-network-view") : { main-camera = self get-main-camera. main-camera look at (0,VIEW_HEIGHT,0) from ((0.1,-0.1,10) * VIEW_DISTANCE). } else { self offset-camera by (0, CAMERA_HEIGHT, -20). self watch item player. } + to all-monsters-dead: i (int). for i=0, i<|monsters|, i++ : { # Monster not dead if (monsters{i} get-deaths) == 0 : { return 0. } } return 1. + to increment-deaths: deaths++. kills-last-gen++. + to get-player-location: return (player get-location). + to get-player: return player. + to get-goal: return goal. # Monster Info + to next-theta-location: return (triangulate next-theta-location). + to get-team-size: return ( |monsters| ). + to get-monsters: return monsters. # damage: damage dealt to player + to assign-damage-assist of damage (double): i (int). neighbors (list). neighbors = (player get-neighbors). for i=0, i<|neighbors|, i++ : { if (neighbors{i} is a "Monster") && ((neighbors{i} get-distance from player) < (commandline num-param named "very-close-player")) : { neighbors{i} increase-damage-assist by damage. } } + to get-additional-input-info: return additional-input-info. + to get-monster-starting-weights: if |monster-starting-weights| == 0 : { print "Starting weights asked for at a point where they've been freed". self end-simulation. } else return monster-starting-weights. + to get-bot-color: if current-game-mode < (graphics get-num-bot-colors) : return (graphics get-bot-color for-mode current-game-mode). else return (graphics get-bot-color for-mode 0). # Evolution # brains: list of lists of neural network brains + to give-monsters-starting-brains from brains (list): i (int). j (int). monster-index (int). pop-slot (int). pop-slot = 0. for i = 0, i < number-of-subpops, i++ : { for j = 0, j < monsters-from-each-subpop, j++ : { if (homogeneous == 0) : pop-slot = j. monster-index = ((i * monsters-from-each-subpop) + j). monsters{ monster-index } replace-brain with-genome ( brains{i}{pop-slot} ). monsters{ monster-index } assign-subpop-index of i. monsters{ monster-index } set-population-slot to pop-slot. monsters{ monster-index } remember-index of monster-index. } } + to get-number-of-subpops: return number-of-subpops. + to get-innovation-counter: return (ga get-innovation-counter). + to random-weight: return (ga random-weight). # Power ups + to player-gets-powerup: player-powerups++. + to get-num-player-powerups: return player-powerups. # Scores # damage: damage player dealt to a monster + to increase-player-score by damage (double): player-score += damage. # amount: damage a monster dealt to the player + to adjust-group-score by amount (double): i (int). group-score += amount. for i = 0, i < |monsters|, i++ : { monsters{i} group-damage-inflicted amount amount. } + to get-fitness-info-list: return fitness-info-list. # Replacing the population # keeper-ids: list of indicies either within parent-fitnesses # or corresponding to an index in child-fitnesses + to pick-new-parents from keeper-ids (list): i (int). j (int). keeper-hash (hash). key (int). temp-brains (list). parent-offset (int). children-kept (int). brains-needed (int). children-kept = 0. brains-needed = 0. # Each j is a subpopulation for j = 0, j < |keeper-ids|, j++ : { parent-offset = |parent-brains{j}|. temp-brains = parent-brains{j}. foreach key in keys( keeper-hash ) : keeper-hash{key} = 0. # Free the non-keepers to avoid memory leaks. # First remember who to keep. for i = 0, i < |keeper-ids{j}|, i++ : { keeper-hash{ keeper-ids{j}{i} } = 1. } # Free non-keeper parents for i = 0, i < |parent-brains{j}|, i++ : { if !(keeper-hash{i} == 1) : { # Results in a NULL pointer in the list free (parent-brains{j}{i}). free (parent-fitnesses{j}{i}). } } # Prepare to delete non-keeper children, but keep them around until after # network output is performed, just in case for i = 0, i < |child-brains{j}|, i++ : { if !(keeper-hash{ (parent-offset + i) } == 1) : (child-brains{j}{i}) prepare-to-die. else children-kept++. } parent-brains{j} = {}. # Rearrange keepers for i = 0, i < |keeper-ids{j}|, i++ : { push (self keeper-choose index (keeper-ids{j}{i}) parents (temp-brains) children (child-brains{j})) onto parent-brains{j}. brains-needed++. } temp-brains = {}. } ratio-children-in-new-pop = (children-kept * 1.0) / (brains-needed * 1.0). if (commandline bit-param named "mutation-inverse-child-rate") : self update-child-ratio-mutation-rates. self give-monsters-starting-brains from parent-brains. self reset-shuffle-offset. # Given a keeper index, return the appropriate result from a list of # parent or children data + to keeper-choose index i (int) parents parents (list) children children (list): if i < |parents| : { return (parents{i}). } else { return (children{ (i - |parents|) }). } + to get-random-children: i (int). j (int). k (int). newBrain (object). source-subpop (int). child-brains = {}. for j=0, j<|parent-brains|, j++ : { push {} onto child-brains. for i=0, i<|parent-brains{j}|, i++ : { for k = 0, k < children-per-parent, k++ : { source-subpop = j. # Change source-subpop if there is a chance of cross-breeding if ((random[1.0]) < (commandline num-param named "cross-breed-percentage")) : source-subpop = random[ (|parent-brains| - 1) ]. if (commandline bit-param named "mating") : { newBrain = (self new-offspring of source-subpop). } else if (commandline bit-param named "binary-tournament") : { newBrain = (self get-mutated-binary-tournament-champion from source-subpop). } else { newBrain = (self get-mutated-child from i of source-subpop). } push newBrain onto (child-brains{j}). } } } self give-monsters-starting-brains from child-brains. self reset-shuffle-offset. # Can't be used with the ZScores method + to get-mutated-binary-tournament-champion from source-subpop (int): choice1 (int). choice2 (int). choice1 = random[ ( |parent-brains{source-subpop}| - 1 ) ]. choice2 = random[ ( |parent-brains{source-subpop}| - 1 ) ]. if (selection dominate this ( parent-fitnesses{source-subpop}{choice1} ) dominates ( parent-fitnesses{source-subpop}{choice2} ) ) : { return (self get-mutated-child from choice1 of source-subpop). } else { return (self get-mutated-child from choice2 of source-subpop). } + to get-num-inputs: i (int). inputs (int). inputs = 0. for i = 0, i < |(self get-additional-input-info)|, i++ : { inputs++. } return inputs. + to new-starting-brain: i (int). inputs (int). brain (object). pos1 (int). pos2 (int). weight (double). inputs = (self get-num-inputs). brain = new FreeNetwork. if (commandline bit-param named "fs-net") : brain initialize-basic-structure with-weights (self get-monster-starting-weights). else brain random-initialize with-inputs inputs and-outputs (commandline num-param named "num-output-neurons"). # Give a single starting connection if (commandline bit-param named "fs-net") : { # Each output gets a connection for i = 0, i < (commandline num-param named "num-output-neurons"), i++ : { pos1 = random[ ((brain get-number-inputs) - 1) ]. pos2 = (brain get-number-inputs) + i. weight = (self random-weight). brain add-connection-between-nodes at-position pos1 and pos2 with-synaptic-weight weight. } } return brain. # subpop: index of a subpopulation + to new-offspring of subpop (int): return (self get-new-offspring of subpop within ( |parent-brains{subpop}| - 1 )). # subpop: index of a subpopulation # upper-limit: index of maximum index in subpopulation from which offspring can be derived + to get-new-offspring of subpop (int) within upper-limit (int): choice1 (int). choice2 (int). parent1 (object). parent2 (object). newNet (object). choice1 = (random[(upper-limit)]). while choice1 == choice2 : { choice2 = (random[(upper-limit)]). } parent1 = parent-brains{subpop}{choice1}. parent2 = parent-brains{subpop}{choice2}. newNet = ga crossover this-genome parent1 with-this-genome parent2. # Modifies existing net ga mutate genome newNet. return newNet. + to burst-mutations population brains (list): i (int). j (int). k (int). for i = 0, i < number-of-subpops, i++ : { for j = 0, j < subpop-size, j++ : { for k = 0, k < (commandline num-param named "num-burst-mutations"), k++ : ga mutate genome (brains{i}{j}). } } # subpop: index of a subpopulation # pos: index in subpopulation + to get-mutated-child from pos (int) of subpop (int): return (self get-mutated-child-given-brains brains (parent-brains{subpop}) from pos). + to get-mutated-child-given-brains brains parents (list) from pos (int): newNet (object). newNet = (parents{pos}) copy. ga mutate genome newNet. return newNet. # subpop: index of a subpopulation + to merge-fitnesses of subpop (int): i (int). j (int). fitnesses (list). offset (int). individual-scores (list). fitnesses = {}. if (commandline bit-param named "keep-parents") : { offset = |parent-fitnesses{subpop}|. for i=0, i<|parent-fitnesses{subpop}|, i++ : { individual-scores = {}. for j = 0, j < |parent-fitnesses{subpop}{i}|, j++ : { if (fitness-info-list{j}{SLOT_USE_OBJECTIVE} == FITNESS_OBJECTIVE_ON) : { push (parent-fitnesses{subpop}{i}{j}) onto individual-scores. } } push { i, individual-scores } onto fitnesses. } } else offset = 0. for i=0, i<|child-fitnesses{subpop}|, i++ : { individual-scores = {}. for j = 0, j < |child-fitnesses{subpop}{i}|, j++ : { if (fitness-info-list{j}{SLOT_USE_OBJECTIVE} == FITNESS_OBJECTIVE_ON) : { push (child-fitnesses{subpop}{i}{j}) onto individual-scores. } } push { (i + offset), individual-scores } onto fitnesses. } return fitnesses. # Checks to see if a set of scores achieves all goals, even # goals for disabled objectives. + to passes-all-goals scores s (list): i (int). result (int). result = 1. for i = 0, i<|fitness-info-list|, i++ : { if( (fitness-info-list{i}{SLOT_USE_GOAL}) && (s{i} < fitness-info-list{i}{SLOT_GOAL}) ) : { result = 0. return 0. } } return result. # count individuals that achieve all goals + to count-goal-achievers from keeper-ids (list): j (int). k (int). scores (list). num-achieved-all-goals = 0. for j=0, j<|keeper-ids|, j++ : { # each k corresponds to an individual in subpopulation j for k=0, k<|keeper-ids{j}|, k++ : { # Depending on the value of the keeper id, the information about the individual # may be in the parent fitness list or the child fitness list scores = (self keeper-choose index (keeper-ids{j}{k}) parents (parent-fitnesses{j}) children (child-fitnesses{j})). if (self passes-all-goals scores scores) : num-achieved-all-goals++. } } # keeper-ids: list of indicies either within parent-fitnesses # or corresponding to an index in child-fitnesses + to update-best-and-worst-fitnesses from keeper-ids (list): i (int). j (int). k (int). n (int). value (double). scores (list). for i = 0, i<|fitness-info-list|, i++ : { fitness-info-list{i}{SLOT_CURRENT_BEST_FITNESS} = -INFINITY. fitness-info-list{i}{SLOT_CURRENT_WORST_FITNESS} = INFINITY. fitness-info-list{i}{SLOT_CURRENT_AVE} = 0.0. } # each i corresponds to a particular fitness objective for i=0, i<|fitness-info-list|, i++ : { # n is the number of individuals added up to take the average of n = 0. # each j corresponds to a single subpopulation for j=0, j<|keeper-ids|, j++ : { # each k corresponds to an individual in subpopulation j for k=0, k<|keeper-ids{j}|, k++ : { # Depending on the value of the keeper id, the information about the individual # may be in the parent fitness list or the child fitness list scores = (self keeper-choose index (keeper-ids{j}{k}) parents (parent-fitnesses{j}) children (child-fitnesses{j})). value = scores{i}. n++. fitness-info-list{i}{SLOT_CURRENT_AVE} += (value - fitness-info-list{i}{SLOT_CURRENT_AVE})/n. if value > (fitness-info-list{i}{SLOT_CURRENT_BEST_FITNESS}) : { fitness-info-list{i}{SLOT_CURRENT_BEST_FITNESS} = value. fitness-info-list{i}{SLOT_FULL_SCORES_OF_BEST} = scores. } if value < (fitness-info-list{i}{SLOT_CURRENT_WORST_FITNESS}) : { fitness-info-list{i}{SLOT_CURRENT_WORST_FITNESS} = value. } } } } if file-output : log log-data using fitness-info-list to-file experiment-theme. # Is called at the end of every sequence of parent evaluations and # every sequence of child evaluations + to end-phase: i (int). j (int). k (int). finalscores (object). temp (string). temp2 (string). tempDouble (double). switch (int). write (int). end (int). if (home-stretch == 1) : home-stretch-counter = home-stretch-counter + 1. if (commandline num-param named "switch-every") > 0 : { switch = ((current-population == POPULATION_PARENTS) && (generation > 0) && (generation % (commandline num-param named "switch-every") == 0)). } else { switch = user-increase-challenge || ( ((self get-player-strategy) != STRATEGY_HUMAN) && # No incremental evolution against humans (current-population == POPULATION_PARENTS) && # Means a child generation just finished (((commandline bit-param named "use-fitness-goals") == 0) || (self check-fitness-goals)) && (((commandline bit-param named "use-log-goals") == 0) || (log check-goals)) ). } end = (generation >= (commandline num-param named "max-gens")) || user-end || (home-stretch-counter == (commandline num-param named "home-stretch-generations")). write = (generation > (2 + (commandline num-param named "ending-generation"))) && #Don't write networks if already written within 2 gens ((switch && (home-stretch-counter <= 0)) || user-save || ((generation > 0) && (current-population == POPULATION_CHILDREN) && (generation % (commandline num-param named "gens-between-write") == 0)) || end). if switch && (commandline bit-param named "make-movie") && (!movie) : { movie = new Movie. movie record to "$file-path/$experiment-theme$generation.mpg". switch = 0. write = 0. } phase++. if write && file-output : { self end-phase-write is-switch switch is-end end. } # changing tasks if switch : { if movie : { movie close. free movie. } if (commandline bit-param named "progress") : { end = (self increase-challenge) || end. # if end became true, then we need to write the last population (in case we haven't already) if (end == 1) && (write == 0): { self end-phase-write is-switch switch is-end end. } } } if end : { temp = (commandline string-param named "name"). temp = "FinalScores-$temp.txt". finalscores = new File. finalscores open-for-writing with-file temp. finalscores write-line text "#parent-fitnesses". for i = 0, i < |parent-fitnesses|, i++ : { finalscores write-line text "#subpop $i". temp = "#". for k = 0, k < |fitness-info-list|, k++ : { temp2 = fitness-info-list{k}{SLOT_DISPLAY_LABEL}. temp = "$temp$temp2\t". } finalscores write-line text temp. for j = 0, j < |parent-fitnesses{i}|, j++ : { temp = "". for k = 0, k < |parent-fitnesses{i}{j}|, k++ : { tempDouble = parent-fitnesses{i}{j}{k}. temp = "$temp$tempDouble\t". } finalscores write-line text temp. } } finalscores write-line text "#child-fitnesses". for i = 0, i < |child-fitnesses|, i++ : { finalscores write-line text "#subpop $i". temp = "#". for k = 0, k < |fitness-info-list|, k++ : { temp2 = fitness-info-list{k}{SLOT_DISPLAY_LABEL}. temp = "$temp$temp2\t". } finalscores write-line text temp. for j = 0, j < |child-fitnesses{i}|, j++ : { temp = "". for k = 0, k < |child-fitnesses{i}{j}|, k++ : { tempDouble = child-fitnesses{i}{j}{k}. temp = "$temp$tempDouble\t". } finalscores write-line text temp. } } finalscores close. print "Final scores written to file". if user-end : print "User terminates simulation". print "Ending Simulation". self end-simulation. return. } self free-doomed-children. # Free networks in child population whose "prepared to die" value is set + to free-doomed-children: i (int). j (int). # Now that network output is done, free the children that should have # been deleted earlier for j = 0, j < |child-brains|, j++ : { for i = 0, i < |child-brains{j}|, i++ : { if ((child-brains{j}{i}) is-ready-to-die) : { free (child-brains{j}{i}). free (child-fitnesses{j}{i}). } } } # If files are to be written at the end of a phase, this # method is called. + to end-phase-write is-switch switch (int) is-end end (int): tempInt (int). ident (string). populations-logged (int). temp (string). if switch : commandline set-bit-param named "progress-on-resume" to COMMAND_LINE_ON. #self report-object-allocation. self update-end-generation. populations-logged = log get-populations-logged. tempInt = (self get-player-strategy). ident = "Strat$tempInt". temp = (commandline num-param named "speed-difficulty"). ident = "Speed$temp$ident". if (switch == 1) : ident = "Switch$ident". else ident = "Checkpoint$ident". if (end == 1) : ident = "End$ident". ident = "Gen$generation$ident". ident = "$experiment-theme$populations-logged$ident". if (user-save == 1) : ident = "User-Save-$ident". self log-to-file text "#$experiment-theme - Write networks: $ident". if (commandline bit-param named "network-output") || (end == 1) : { self write-networks with-identifier ident. } log increment-populations-logged. user-save = 0. # Used for incremental evolution. # Depending on the command-line settings, either the movement speed # of the bot will be increased, or the bot will start exhibiting a different # sort of behavior. + to increase-challenge: end (int). i (int). s (double). shaping-index (int). user-increase-challenge = 0. end = 0. if use-shaping : { shaping-index = (commandline num-param named "index-of-last-shaping-objective-added"). shaping-index++. if ( shaping-index == |fitness-info-list| ) : { end = 1. } else { fitness-info-list{shaping-index}{SLOT_USE_OBJECTIVE} = FITNESS_OBJECTIVE_ON. commandline set-num-param named "index-of-last-shaping-objective-added" to shaping-index. } } else { for i = 0, i < |fitness-info-list|, i++ : { # Make sure objectives are on in case they were turned off by "ldo" fitness-info-list{i}{SLOT_USE_OBJECTIVE} = FITNESS_OBJECTIVE_ON. } } self decrease-stagnation-threshold. if (commandline bit-param named "task-progression") == 0 : { # Speed progression if (commandline num-param named "speed-difficulty") < 1.0 : { if (commandline bit-param named "use-speed-sequence") : { self next-in-speed-sequence. } else { self set-speed-difficulty to (min(1.0, (commandline num-param named "speed-difficulty") + (commandline num-param named "speed-jump"))). } } else end = 1. if ((commandline num-param named "speed-difficulty") == 1.0) : home-stretch = 1. # Doesn't change anything, but resets stats self switch-strategy to (self get-player-strategy). } else { # Task progression if (self get-player-strategy) == STRATEGY_STILL : (self switch-strategy to STRATEGY_SPIN). else if (self get-player-strategy) == STRATEGY_SPIN : (self switch-strategy to STRATEGY_COMBO). else if (self get-player-strategy) == STRATEGY_COMBO : (self switch-strategy to STRATEGY_SMART). else if (self get-player-strategy) == STRATEGY_SMART : end = 1. if (self get-player-strategy) == STRATEGY_SMART : home-stretch = 1. } if (home-stretch == 1) && ((commandline num-param named "home-stretch-generations") > -1) : { if home-stretch-counter < (commandline num-param named "home-stretch-generations") : { end = 0. } else { end = 1. } } #if end == 1 and there is a commandline option to turn on TUG-2.0, #then end should be set to 0 and all goals should be increased according to # SLOT_GOAL <- SLOT_GOAL + s * (SLOT_CURRENT_BEST_FITNESS - SLOT_GOAL) # where s is another commandline parameter if ((end == 1) && (commandline bit-param named "increase-goals-when-all-achieved")) : { end = 0. s = (commandline num-param named "goal-increase-alpha"). for i = 0, i < |fitness-info-list|, i++ : { if(fitness-info-list{i}{SLOT_USE_GOAL}) : fitness-info-list{i}{SLOT_GOAL} += s * (fitness-info-list{i}{SLOT_CURRENT_BEST_FITNESS} - fitness-info-list{i}{SLOT_GOAL}). } } if (commandline bit-param named "open-ended-evolution") : end = 0. return end. + to decrease-challenge: if (commandline bit-param named "task-progression") == 0 : { # Speed progression if (commandline num-param named "speed-difficulty") > 0.0 : (self set-speed-difficulty to (max(0.0, (commandline num-param named "speed-difficulty") - (commandline num-param named "speed-jump")))). # Doesn't change anything, but resets stats self switch-strategy to (self get-player-strategy). } else { # Task progression if (self get-player-strategy) == STRATEGY_SPIN : (self switch-strategy to STRATEGY_STILL). else if (self get-player-strategy) == STRATEGY_COMBO : (self switch-strategy to STRATEGY_SPIN). else if (self get-player-strategy) == STRATEGY_SMART : (self switch-strategy to STRATEGY_COMBO). } home-stretch = 0. home-stretch-counter = 0. # Checks if the population as a whole has obtained high enough fitness values # to meet all goals. Goals can be specified for each fitness objective, and they # are considered met if the average fitness of the population for that objective # has reached the goal defined for that objective. + to check-fitness-goals: i (int). j (int). failed (int). scores (list). num-achieved (int). num-needed (int). failed = 0. for i = 0, i < |fitness-info-list|, i++ : { if ( fitness-info-list{i}{SLOT_USE_GOAL} == FITNESS_GOAL_ON ) : { if (commandline bit-param named "champion-over-all-objectives") : { # First, the moving average of the best score has to cross the threshold if ( fitness-info-list{i}{SLOT_GOAL} > fitness-info-list{i}{SLOT_BEST_AVE} ) : { failed++. } else { # Then get all scores of the best in each objective scores = fitness-info-list{i}{SLOT_FULL_SCORES_OF_BEST}. # Champion has to mett all other objectives as well num-achieved = 0. num-needed = 0. for j = 0, j < |scores|, j++ : { if ( fitness-info-list{j}{SLOT_USE_GOAL} == FITNESS_GOAL_ON ) : { num-needed++. if ( scores{j} > fitness-info-list{j}{SLOT_GOAL} ) : { num-achieved++. } } } if ( num-needed != num-achieved ) : { failed++. } } } if !(commandline bit-param named "champion-over-all-objectives") || (commandline bit-param named "coa-and-pop-avg-beats-goal") : { if ( fitness-info-list{i}{SLOT_GOAL} > fitness-info-list{i}{SLOT_CURRENT_AVE_AVE} ) || ( fitness-info-list{i}{SLOT_GOAL} > fitness-info-list{i}{SLOT_CURRENT_AVE} ) : { # Has not beaten goal yet failed++. if drop-defeated : { # Always restore objectives that are not beaten fitness-info-list{i}{SLOT_USE_OBJECTIVE} = FITNESS_OBJECTIVE_ON. } } else { # beat the goal (except for RANDOM) if drop-defeated && (fitness-info-list{i}{SLOT_DISPLAY_LABEL} != "Random") : { # Don't base selection on defeated goals fitness-info-list{i}{SLOT_USE_OBJECTIVE} = FITNESS_OBJECTIVE_OFF. } } } } } if failed > 0 : return 0. else return 1. + to reset-fitness-averages: i (int). tempList (list). for i = 0, i < |fitness-info-list|, i++ : { fitness-info-list{i}{SLOT_CURRENT_AVE_AVE} = fitness-info-list{i}{SLOT_MIN}. fitness-info-list{i}{SLOT_BEST_AVE} = fitness-info-list{i}{SLOT_MIN}. fitness-info-list{i}{SLOT_WORST_AVE} = fitness-info-list{i}{SLOT_MIN}. } # Since there are no champions at the start of the simulation, # the slot for storing the champion's scores holds the worst values tempList = {}. for i = 0, i < |fitness-info-list|, i++ : { push ( fitness-info-list{i}{SLOT_MIN} ) onto tempList. } for i = 0, i < |fitness-info-list|, i++ : { fitness-info-list{i}{SLOT_FULL_SCORES_OF_BEST} = tempList. } # Takes existing fitnesses so far and combines them with scores from the current # evaluation to get a new set of current fitness scores for each evaluated network + to tally-up-fitness-scores: i (int). j (int). pop-slot (int). subpop-num (int). ave-scores-homo (list). individual-scores (list). if homogeneous && (commandline bit-param named "use-worst-scores") : { # Homogeneous mode scores are the average scores across teammates # (this also works if the score is only defined at the group level, since each individual score # will equal the average score) ave-scores-homo = (monsters{0} get-fitnesses). for i=1, i<|monsters|, i++ : { individual-scores = (monsters{i} get-fitnesses). for j=0, j<|ave-scores-homo|, j++ : { ave-scores-homo{j} = ave-scores-homo{j} + individual-scores{j}. } } for j=0, j<|ave-scores-homo|, j++ : { ave-scores-homo{j} = ave-scores-homo{j} / (1.0 * |monsters|). } # Now, set the stored fitness score to the min of the current score and the previous score. # In a homogeneous population, the pop-slot and subpop-num of each monster should be the same. pop-slot = monsters{0} get-population-slot. subpop-num = monsters{0} get-subpop-index. if ( |current-fitnesses{subpop-num}{pop-slot}| == 0 ) : current-fitnesses{subpop-num}{pop-slot} = ave-scores-homo. else { for j=0, j<|ave-scores-homo|, j++ : { current-fitnesses{subpop-num}{pop-slot}{j} = min( (current-fitnesses{subpop-num}{pop-slot}{j}), ave-scores-homo{j} ). } } } else { for i=0, i<|monsters|, i++ : { pop-slot = monsters{i} get-population-slot. subpop-num = monsters{i} get-subpop-index. self average-list-scores of-sub subpop-num and-slot pop-slot with (monsters{i}). } } # Takes previous fitness score for network (if exists) and averages with the new scores for each objective. # subpop-num: index of subpopulation # pop-slot: index within individual subpopulation # mon: specific Monster object # - Side-effects to list stored in old + to average-list-scores of-sub subpop-num (int) and-slot pop-slot (int) with mon (object): i (int). extra (list). old (list). old = current-fitnesses{subpop-num}{pop-slot}. extra = mon get-fitnesses. type-trials-for-brains{subpop-num}{pop-slot}{current-game-mode} = type-trials-for-brains{subpop-num}{pop-slot}{current-game-mode} + 1. # After first eval, initialize fitnesses if |old| == 0 : { for i=0, i<|extra|, i++: { push 0.0 onto old. } } for i=0, i<|old|, i++ : { if (fitness-info-list{i}{SLOT_GAME_MODE} == current-game-mode) : { old{i} += ((extra{i} - old{i}) / ((type-trials-for-brains{subpop-num}{pop-slot}{current-game-mode}) * 1.0)). } else if (fitness-info-list{i}{SLOT_GAME_MODE} == GAME_MODE_ALL) : { old{i} += ((extra{i} - old{i}) / (math summation of (type-trials-for-brains{subpop-num}{pop-slot}))). } } # Store behavior vectors in current-behavior-vectors + to gather-behavior-vectors: i (int). pop-slot (int). subpop-num (int). for i=0, i<|monsters|, i++ : { pop-slot = monsters{i} get-population-slot. subpop-num = monsters{i} get-subpop-index. # Only gather behavior vectors for individual if not done yet if (|current-behavior-vectors{subpop-num}{pop-slot}| == 0) : { current-behavior-vectors{subpop-num}{pop-slot} = (behavior-state get-behavior-vector given monsters index-of i). } } + to track-mode-usage: pop-slot (int). subpop-num (int). i (int). for i = 0, i < |monsters|, i++ : { pop-slot = monsters{i} get-population-slot. subpop-num = monsters{i} get-subpop-index. if ( current-mode-usage{subpop-num}{pop-slot} == {} ) : current-mode-usage{subpop-num}{pop-slot} = (monsters{i} get-mode-usage). else self hash-merge modify (current-mode-usage{subpop-num}{pop-slot}) same (monsters{i} get-mode-usage). } + to hash-merge modify a (hash) same b (hash): key (int). foreach key in keys( b ) : { a{key} = b{key}. } + to percent-mode-usage subpopulation subpop-num (int) id pop-slot (int): total-used (int). net (object). brains (list). total-modes (int). tempHash (hash). key-list (list). #key (int). percent (double). tempHash = (current-mode-usage{subpop-num}{pop-slot}). key-list = keys(tempHash). #foreach key in key-list : print key, ":", tempHash{key}. total-used = |key-list|. if (current-population == POPULATION_PARENTS) : brains = parent-brains. else if (current-population == POPULATION_CHILDREN) : brains = child-brains. net = brains{subpop-num}{pop-slot}. total-modes = (mode-arbitrator get-num-output-modes-from-net network net). percent = ((1.0 * total-used) / (1.0 * total-modes)). if (percent > 1.0) : { print "Impossible mode usage". if (current-population == POPULATION_PARENTS) : print "Parents". else if (current-population == POPULATION_CHILDREN) : print "Children". print "$total-used / $total-modes = $percent". net print-network. self end-simulation. } return percent. # Called after every evaluation + to end-eval: i (int). #j (int). current-iteration = 0. current-eval++. kills-last-gen = 0. type-trials{current-game-mode} = type-trials{current-game-mode} + 1. if current-game-mode == MODE_PREY : { ave-player-prey-score += (player-score - ave-player-prey-score)/(type-trials{current-game-mode}). } else if current-game-mode == MODE_PRED : { ave-group-pred-score += (group-score - ave-group-pred-score)/(type-trials{current-game-mode}). } else if current-game-mode == MODE_FIGHT : { ave-group-fight-score += (group-score - ave-group-fight-score)/(type-trials{current-game-mode}). ave-player-fight-score += (player-score - ave-player-fight-score)/(type-trials{current-game-mode}). } if (current-game-mode == MODE_FIGHT || current-game-mode == MODE_PRED) : ave-group-score += (group-score - ave-group-score)/((type-trials{MODE_PRED}) + (type-trials{MODE_FIGHT})). if (current-game-mode == MODE_FIGHT || current-game-mode == MODE_PREY) : ave-player-score += (player-score - ave-player-score)/((type-trials{MODE_PREY}) + (type-trials{MODE_FIGHT})). self tally-up-fitness-scores. if behavior-diversity : self gather-behavior-vectors. group-score = 0. player-score = 0. player-powerups = 0. # Get hash data from monster and store it if (commandline bit-param named "track-mode-usage") : { self track-mode-usage. } if current-eval == (self get-real-num-evals) : { #SMEG: temp code to test "percent-mode-usage" #if (commandline bit-param named "track-mode-usage") : #{ # for i = 0, i < |current-mode-usage|, i++ : # { # for j = 0, j < |current-mode-usage{i}|, j++ : # { # print (self percent-mode-usage subpopulation i id j). # } # } #} if current-population == POPULATION_PARENTS : { self end-parent-eval-phase. } else if current-population == POPULATION_CHILDREN : { log update-log-averages. self end-child-eval-phase. if random-behavior-syllabus : { # The syllabus changes whenever the whole population changes behavior-state randomize-syllabus length (self get-num-inputs). } } for i=0, i<|fitness-info-list|, i++ : { fitness-info-list{i}{SLOT_BEST_AVE} += recency-weighted-alpha * (fitness-info-list{i}{SLOT_CURRENT_BEST_FITNESS} - fitness-info-list{i}{SLOT_BEST_AVE}). fitness-info-list{i}{SLOT_WORST_AVE} += recency-weighted-alpha * (fitness-info-list{i}{SLOT_CURRENT_WORST_FITNESS} - fitness-info-list{i}{SLOT_WORST_AVE}). fitness-info-list{i}{SLOT_CURRENT_AVE_AVE} += recency-weighted-alpha * (fitness-info-list{i}{SLOT_CURRENT_AVE} - fitness-info-list{i}{SLOT_CURRENT_AVE_AVE}). } # At this point, the "current-population" will have already been switched self end-phase. current-eval = 0. self blank-current-fitnesses. self zero-scores. } else { # Reset their scores for i=0, i<|monsters|, i++ : monsters{i} reset. } self switch-current-game-mode. self spawn-player. + to end-parent-eval-phase: if behavior-diversity : { free parent-behavior-vectors. parent-behavior-vectors = current-behavior-vectors. } free parent-fitnesses. parent-fitnesses = current-fitnesses. self get-random-children. self update-starting-innovation-counter. current-population = POPULATION_CHILDREN. # pick the last population so that immediate incrementing and modulus leads back to zero if homogeneous : current-population-num = ((subpop-size * children-per-parent) - 1). else current-population-num = (((subpop-size * children-per-parent) / monsters-from-each-subpop) - 1). + to end-child-eval-phase: i (int). j (int). #k (int). #sum (double). diversity (double). keeper-ids (list). #t (int). free child-fitnesses. child-fitnesses = current-fitnesses. if behavior-diversity : { #print "parent-behavior-vectors =", parent-behavior-vectors. #print "current-behavior-vectors =", current-behavior-vectors. # Add current-behavior-vectors to parent-behavior-vectors to get all # vectors in one list, with parent vectors at the front. Technically, # parent-behavior-vectors contains child vectors as well at this point. # First go through each subpop for i = 0, i < |current-behavior-vectors|, i++ : { for j = 0, j < |current-behavior-vectors{i}|, j++ : { push (current-behavior-vectors{i}{j}) onto (parent-behavior-vectors{i}). } } # parent-behavior-vectors now contains ALL behavior vectors (parent and child) #print "parent-behavior-vectors =", parent-behavior-vectors. # Now compare each behavior vector to all others to get the average distance # from the rest of population # Deprecated: Each task #for t = 0, t < |tasks|, t++ : #{ # Each subpop for i = 0, i < |parent-behavior-vectors|, i++ : { # Each individual for j = 0, j < |parent-behavior-vectors{i}|, j++ : { #sum = 0. # Compare to every other individual #for k = 0, k < |parent-behavior-vectors{i}|, k++ : #{ # if (j != k) : # { # #sum += (behavior-state get-euclidean-distance between (parent-behavior-vectors{i}{j}{t}) # # and (parent-behavior-vectors{i}{k}{t})). # sum += (behavior-state get-euclidean-distance between (parent-behavior-vectors{i}{j}) # and (parent-behavior-vectors{i}{k})). # } #} #diversity = (sum / (|parent-behavior-vectors{i}| - 1)). diversity = (behavior-state get-average-euclidean-distance of j within (parent-behavior-vectors{i})). if (j < |parent-fitnesses{i}|) : # Add to parent fitnesses { #print "parent-fitnesses{$i}{$j} =", parent-fitnesses{i}{j}. #parent-fitnesses{i}{j}{(tasks{t}{TASK_DIVERSITY_FITNESS_INDEX})} = diversity. parent-fitnesses{i}{j}{diversity-fitness-index} = diversity. #print "parent-fitnesses{$i}{$j} =", parent-fitnesses{i}{j}. } else { # Add to child fitnesses #print "child-fitnesses{$i}{$j - ...} =", child-fitnesses{i}{(j - |parent-fitnesses{i}|)}. #child-fitnesses{i}{(j - |parent-fitnesses{i}|)}{(tasks{t}{TASK_DIVERSITY_FITNESS_INDEX})} = diversity. child-fitnesses{i}{(j - |parent-fitnesses{i}|)}{diversity-fitness-index} = diversity. #print "child-fitnesses{$i}{$j - ...} =", child-fitnesses{i}{(j - |parent-fitnesses{i}|)}. } } } #} free parent-behavior-vectors. free current-behavior-vectors. } keeper-ids = {}. for i = 0, i < number-of-subpops, i++ : { push {} onto keeper-ids. keeper-ids{i} = (selection get-best choose (|parent-fitnesses{i}|) of-population (self merge-fitnesses of i)). } stagnation-counter++. if (stagnation-counter > (commandline num-param named "stagnation-threshold")) : { self increase-stagnation-threshold. self zero-scores. log reset-log-averages. if (commandline bit-param named "burst-mutation-after-stagnation") : { # Many mutations to get unstuck self pick-new-parents from keeper-ids. self burst-mutations population parent-brains. } else { # Do all networks need to be freed? self load-last-save. } stagnation-counter = 0. if (commandline bit-param named "easier-after-stagnation") : self decrease-challenge. } else { selection advance-generation. self pick-new-parents from keeper-ids. self count-goal-achievers from keeper-ids. self update-best-and-worst-fitnesses from keeper-ids. } current-population = POPULATION_PARENTS. current-population-num = ((subpop-size / monsters-from-each-subpop) - 1). # Environment + to draw-net net theNet (object): if view: view draw net theNet. + to get-math: return math. + to get-behavior-state: return behavior-state. + to get-mode-arbitrator: return mode-arbitrator. + to get-commandline: return commandline. + to get-graphics: return graphics. + to get-triangulate: return triangulate. + to reset-shuffle-offset: shuffle-offset = subpop-size - SHUFFLE_JUMP. + to make-walls: wallSize (vector). wallColor (vector). wallSize = (1,(HALF_WALL_HEIGHT * 2),(HALF_WALL_LENGTH * 2)). wallColor = (0,0,1). new Wall create at (-HALF_WALL_LENGTH,HALF_WALL_HEIGHT,0) size wallSize color wallColor. new Wall create at (HALF_WALL_LENGTH,HALF_WALL_HEIGHT,0) size wallSize color wallColor. wallSize = ((HALF_WALL_LENGTH * 2),(HALF_WALL_HEIGHT * 2),1). new Wall create at (0,HALF_WALL_HEIGHT,-HALF_WALL_LENGTH) size wallSize color wallColor. new Wall create at (0,HALF_WALL_HEIGHT,HALF_WALL_LENGTH) size wallSize color wallColor. + to place-powerups: new HealthBoost create radius 2.0 color (1,0,1). new SpeedBoost create radius 2.0 color (0,1,1). new GunBoost create radius 2.0 color (1,0.5,0). # Monster positions + to player-is-surrounded: return (triangulate is-surrounded by monsters point-at (player get-location)). # loc: position on plane # direction: points out from the given position + to get-angle-to-monster-center from loc (vector) facing direction (vector): return (triangulate get-angle-to-center from loc facing direction given monsters). # loc: position on plane # direction: points out from the given position + to get-angle-to-nearest-monster-in-front from loc (vector) facing direction (vector): return (triangulate get-angle-to-nearest-monster-in-front from loc facing direction given monsters). # monster1: index in list monsters # monster2: index in list monsters # - monster1 != monster2 + to get-signed-neg-difference-in-heading-from-heading-rear of monster1 (int) to monster2 (int): return (triangulate get-signed-neg-difference-in-heading-from-heading-rear of monster1 to monster2 given monsters). # monster1: index in list monsters # monster2: index in list monsters # - monster1 != monster2 + to get-signed-neg-angle-from-rear of monster1 (int) to monster2 (int): return (triangulate get-signed-neg-angle-from-rear of monster1 to monster2 given monsters). # mon: monster object + to get-angle-to-monster-nearest to mon (object): if (mon get-deaths) > 0 : return 0. return (triangulate get-angle-to-nearest-object from (mon get-location) facing (mon get-facing) given monsters). # mon: monster object + to get-angle-to-bullet-nearest to mon (object): if (mon get-deaths) > 0 : return 0. return (triangulate get-angle-to-nearest-object from (mon get-location) facing (mon get-facing) given (all Bullet)). + to get-close-player-impulse for-index i (int): return (monsters{i} get-close-player-impulse). + to get-very-close-player-impulse for-index i (int): return (monsters{i} get-very-close-player-impulse). }