def dummyLoop(): global maxSpeed, shotAngle, wallClose, dead, previousScore global turnedLeft, turnedRight, thrusted, shot #Release keys DataMinerBD.tthrustDummy(0) DataMinerBD.tturnLeftDummy(0) DataMinerBD.tturnRightDummy(0) ai.setTurnSpeed(45) #Set variables""" heading = int(ai.selfHeadingDeg()) tracking = int(ai.selfTrackingDeg()) trackWall = ai.wallFeeler(500, tracking) trackLWall = ai.wallFeeler(500, tracking + 3) trackRWall = ai.wallFeeler(500, tracking - 3) frontWall = ai.wallFeeler(500, heading) flWall = ai.wallFeeler(500, heading + 10) frWall = ai.wallFeeler(500, heading - 10) leftWall = ai.wallFeeler(500, heading + 90) llWall = ai.wallFeeler(500, heading + 100) rlWall = ai.wallFeeler(500, heading + 80) rightWall = ai.wallFeeler(500, heading - 90) lrWall = ai.wallFeeler(500, heading - 80) rrWall = ai.wallFeeler(500, heading - 100) trackWall = ai.wallFeeler(500, tracking) backWall = ai.wallFeeler(500, heading - 180) backLeftWall = ai.wallFeeler(500, heading - 190) backRightWall = ai.wallFeeler(500, heading - 170) speed = ai.selfSpeed() closest = min(frontWall, leftWall, rightWall, backWall, flWall, frWall) def closestWall(x): #Find the closest Wall return { frontWall: 1, leftWall: 2, rightWall: 3, backWall: 4, flWall: 5, frWall: 6, }[x] wallNum = closestWall(closest) #Code for finding the angle to the closest ship targetX, targetY = ai.screenEnemyX(0), ai.screenEnemyY(0) #baseString = "["+str(flWall/500)+","+str(frontWall/500)+","+str(frWall/500) + "," + str(backLeftWall/500) + "," + str(backWall/500) + "," + str(backRightWall/500) + ","+str(leftWall/500)+","+str(rightWall/500)+","+str(trackLWall/500) + "," + str(trackWall/500) + ","+str(trackRWall/500) + "," + str(speed/10) calcDir = -1 if targetX - ai.selfX() != 0: calcDir = (math.degrees( math.atan2((targetY - ai.selfY()), (targetX - ai.selfX()))) + 360) % 360 crashWall = min( trackWall, trackLWall, trackRWall ) #The wall we are likely to crash into if we continue on our current course #Rules for turning if crashWall > wallClose * speed and closest > 25 and targetX != -1: #If we are far enough away from a predicted crash and no closer than 25 pixels to a wall we can try and aim and kill them diff = (calcDir - heading) #if ai.shotAlert(0) > -1 and ai.shotAlert(0) < 35: #If we are about to get shot # tturnRight(1) #Screw aiming and turn right and thrust # tthrust(1) #This is arguably a horrible strategy because our sideways profile is much larger, but it's required for the grade if diff >= 0: if diff >= 180: DataMinerBD.tturnRightDummy( 1) #If the target is to our right- turn right else: DataMinerBD.tturnLeftDummy( 1) #If the target is to our left - turn left else: if diff > -180: DataMinerBD.tturnRightDummy( 1) #If the target is to our right - turn right else: DataMinerBD.tturnLeftDummy( 1) #If the target is to our left - turn left else: #Rules for avoiding death # if crashWall/ai.selfSpeed() > ai.closestShot() : if wallNum == 1 or wallNum == 5 or wallNum == 6: #Front Wall is Closest (Turn Away From It) DataMinerBD.tturnLeftDummy(1) elif wallNum == 2: # Left Wall is Closest (Turn Away From It) DataMinerBD.tturnRightDummy(1) elif wallNum == 3: #Right Wall is Closest (Turn Away From It) DataMinerBD.tturnLeftDummy(1) else: #Back Wall is closest- turn so that we are facing directly away from it if backLeftWall < backRightWall: DataMinerBD.tturnRightDummy( 1 ) #We need to turn right to face more directly away from it if backLeftWall > backRightWall: # We need to turn left to face more directly away from it DataMinerBD.tturnLeftDummy(1) #Rules for thrusting if speed < maxSpeed and frontWall > 100: #If we are moving slowly and we won't ram into anything, accelerate DataMinerBD.tthrustDummy(1) elif trackWall < 200 and ( ai.angleDiff(heading, tracking) > 120 ): #If we are getting close to a wall, and we can thrust away from it, do so DataMinerBD.tthrustDummy(1) elif backWall < 20: #If there is a wall very close behind us, get away from it DataMinerBD.tthrustDummy(1) if abs( calcDir - heading ) < shotAngle and calcDir != -1: #If we are close to the current proper trajectory for a shot then fire DataMinerBD.tshootDummy() previousScore = ai.selfScore()
def AI_loop(): global count_frame, loop, boolean, score, population_size, chromosome_size, population, mutation_prob, crossover_prob, fitness_list, generation, generation_size, first_time, done_learning #Release keys ai.thrust(0) ai.turnLeft(0) ai.turnRight(0) ## Get A Chromosome in the Population -- Eventually Will go through each individual in the population ## current_chromosome = population[loop] ## Transform Each Gene insisde A Single Selected Chromosome. 0s & 1s Are Turned Into Intergers For Fuzzy Sets to understand ## ## Each Value obtained is used to calculate the risk of each 45 degree around the agent ## ## Each value has its own "jump" variable which refers to the distance from each possible points/values ## ## The start and end represents the possible start point and end point for each variable and they depend on ## what the variiable is. It is to ensure a viable fuzzy set and fuzzy functions that these restrictions are applied. ## frontAlert = current_chromosome[0:5] frontAlertValue = transform(frontAlert, 25) backAlert = current_chromosome[5:9] backAlertValue = transform(backAlert, 25) speedAlert = current_chromosome[9:13] #4 bits speedAlertValue = transform(speedAlert, 1) #1 jumps per value EnemyAlert = current_chromosome[13:18] #5 bits EnemyAlertValue = transform(EnemyAlert, 50) #50 jumps per value TrackSlowAlert = current_chromosome[18:22] #4 bits TrackSlowAlertValue = transform(TrackSlowAlert, 25) #25 jumps per value TrackFastAlert = current_chromosome[22:26] #4 bits TrackFastAlertValue = transform(TrackFastAlert, 25) #25 jumps per value BulletAlert = current_chromosome[26:32] #4 bits BulletAlertValue = transform(BulletAlert, 15) #15 jumps per value ## Get values of variables for Wall Feelers, Head & Tracking ## heading = int(ai.selfHeadingDeg()) tracking = int(ai.selfTrackingDeg()) frontWall = ai.wallFeeler(500,heading) left45Wall = ai.wallFeeler(500,heading+45) right45Wall = ai.wallFeeler(500,heading-45) left90Wall = ai.wallFeeler(500,heading+90) right90Wall = ai.wallFeeler(500,heading-90) left135Wall = ai.wallFeeler(500,heading+135) right135Wall = ai.wallFeeler(500,heading-135) backWall = ai.wallFeeler(500,heading-180) trackWall = ai.wallFeeler(500,tracking) ####### Getters Variable Regarding Important Information About Enemies ######## ##Find the closest ennemy## enemy = ai.lockClose() ## Get the lockheadingdeg of enemy ## head = ai.lockHeadingDeg() ## Get the dstance from enemy ## enemyDist = ai.selfLockDist() ## If the Enemy is Dead ## if(ai.selfAlive() == 0 and boolean == False): ## Calculate Fitness Current Population ## score_previous = score score_current = ai.selfScore() fitness_value = fitness(population, count_frame, score_previous, score_current) fitness_list.append(fitness_value) ## If it went through the whole population and ready to move to next generation ## if((loop+1) == population_size): ## Output the fitness of population to allow user to see if learning is happening ## print("Generation:", generation) print("Agent Fitness:") print(fitness_list) print("Average Fitness:", statistics.mean(fitness_list)) print("Best Fitness:", max(fitness_list)) ## Finding the optimal chromosome to output it in data file ## string_maxChromosome = "" for chrom_max in range(chromosome_size): string_maxChromosome = string_maxChromosome + str(population[fitness_list.index(max(fitness_list))][chrom_max]) ## Formatting entire population in a big string to register it in excel file## string_population = "" for pop in range(population_size): for pop_chrom in range(chromosome_size): string_population = string_population + str(population[pop][pop_chrom]) if(pop != (population_size-1)): string_population = string_population + "," ## Formatting entire population's fitness in a big string to register it in excel file## string_fitness = "" for fit in range(len(fitness_list)): string_fitness = string_fitness + str(fitness_list[fit]) if(fit != (len(fitness_list)-1)): string_fitness = string_fitness + "," ## Output Data into Excel File ## titles = ["Generation", "Average Fitness", "Best Fitness","Population Size", "Chromosome Size", "Crossover Probability", "Mutation Probability", "Best Chromosome", "Entire Population Chromosome", "Entire Population Fitness"] data = [generation, statistics.mean(fitness_list), max(fitness_list), population_size, chromosome_size, crossover_prob, mutation_prob, string_maxChromosome, string_population, string_fitness] first_time = Save_Data("Tiger_Training_Data.xls", 0, titles, data, first_time) ## Select Next Generation -- Apply Crossover & Mutation ## new_population = select(population, fitness_list) new_population = crossover(new_population, chromosome_size, population_size, crossover_prob) new_population = mutate(new_population, chromosome_size, mutation_prob) population = new_population loop = 0 count_frame = 0 generation += 1 fitness_list.clear() ### DONE -- QUIT ### if (generation == generation_size): quitAI() ## Move to the next individual in population ## else: loop += 1 count_frame = 0 boolean = True else: ## The agent is Alive ## if(ai.selfAlive() == 1): ### Turning Rules ### if frontWall <= frontAlertValue and (left45Wall < right45Wall) and ai.selfSpeed() > speedAlertValue: ai.turnRight(1) elif frontWall <= frontAlertValue and (left45Wall > right45Wall) and ai.selfSpeed() > speedAlertValue: ai.turnLeft(1) elif left90Wall <= frontAlertValue and ai.selfSpeed() > speedAlertValue: ai.turnRight(1) elif right90Wall <= frontAlertValue and ai.selfSpeed() > speedAlertValue: ai.turnLeft(1) ### Thrust commands #### elif ai.selfSpeed() <= speedAlertValue and (frontWall >= frontAlertValue) and (left45Wall >= frontAlertValue) and (right45Wall >= frontAlertValue) and (right90Wall >= frontAlertValue) and (left90Wall >= frontAlertValue) and (left135Wall >= backAlertValue) and (right135Wall >= backAlertValue) and (backWall >= backAlertValue): ai.thrust(1) elif trackWall <= TrackFastAlertValue and ai.selfSpeed() >= speedAlertValue: ai.thrust(1) elif trackWall <= TrackSlowAlertValue and ai.selfSpeed() <= speedAlertValue: ai.thrust(1) elif backWall <= TrackFastAlertValue and ai.selfSpeed() >= speedAlertValue: ai.thrust(1) elif backWall <= TrackSlowAlertValue and ai.selfSpeed() <= speedAlertValue: ai.thrust(1) elif left135Wall <= TrackFastAlertValue and ai.selfSpeed() >= speedAlertValue: ai.thrust(1) elif left135Wall <= TrackSlowAlertValue and ai.selfSpeed() <= speedAlertValue: ai.thrust(1) elif right135Wall <= TrackFastAlertValue and ai.selfSpeed() >= speedAlertValue: ai.thrust(1) elif right135Wall <= TrackSlowAlertValue and ai.selfSpeed() <= speedAlertValue: ai.thrust(1) ##### Bullet Avoidance Commands ##### elif ai.shotAlert(0) >= 0 and ai.shotAlert(0) <= BulletAlertValue: if ai.angleDiff(heading, ai.shotVelDir(0)) > 0 and ai.selfSpeed() <= speedAlertValue: ai.turnLeft(1) ai.thrust(1) elif ai.angleDiff(heading, ai.shotVelDir(0)) < 0 and ai.selfSpeed() <= speedAlertValue: ai.turnRight(1) ai.thrust(1) elif ai.angleDiff(heading, ai.shotVelDir(0)) > 0 and ai.selfSpeed() > speedAlertValue: ai.turnLeft(1) else: ai.turnRight(1) ##### Shooting Ennemy Commands ##### elif enemyDist <= EnemyAlertValue and heading > (head) and ai.selfSpeed() > speedAlertValue: ai.turnRight(1) ai.fireShot() elif enemyDist <= EnemyAlertValue and heading < (head) and ai.selfSpeed() > speedAlertValue: ai.turnLeft(1) ai.fireShot() elif ai.selfSpeed() < speedAlertValue: ai.thrust(1) else: ai.thrust(0) count_frame += 3 boolean = False
def AI_loop(): global count_frame, loop, boolean, score, population_size, chromosome_size, population, mutation_prob, crossover_prob, fitness_list, generation, generation_size, first_time, done_learning #Release keys ai.thrust(0) ai.turnLeft(0) ai.turnRight(0) ## Get A Chromosome in the Population -- Eventually Will go through each individual in the population ## current_chromosome = population[loop] ## Transform Each Gene insisde A Single Selected Chromosome. 0s & 1s Are Turned Into Intergers For Fuzzy Sets to understand ## ## Each Value obtained is used to calculate the risk of each 45 degree around the agent ## ## Each value has its own "jump" variable which refers to the distance from each possible points/values ## ## The start and end represents the possible start point and end point for each variable and they depend on ## what the variiable is. It is to ensure a viable fuzzy set and fuzzy functions that these restrictions are applied. ## closingRate_SlowTopAlert = current_chromosome[0:4] closingRate_SlowTopAlertValue = transform_fuzzy(closingRate_SlowTopAlert, 1, 0, 16) closingRate_MediumTopLeftAlert = current_chromosome[4:8] closingRate_MediumTopLeftAlertValue = transform_fuzzy( closingRate_MediumTopLeftAlert, 1, (closingRate_SlowTopAlertValue + 1), (closingRate_SlowTopAlertValue + 1) + 16) closingRate_MediumTopRightAlert = current_chromosome[8:12] closingRate_MediumTopRightAlertValue = transform_fuzzy( closingRate_MediumTopRightAlert, 1, (closingRate_MediumTopLeftAlertValue + 1), (closingRate_MediumTopLeftAlertValue + 1) + 16) closingRate_FastTopAlert = current_chromosome[12:16] closingRate_FastTopAlertValue = transform_fuzzy( closingRate_FastTopAlert, 1, (closingRate_MediumTopRightAlertValue + 1), (closingRate_MediumTopRightAlertValue + 1) + 16) closingRate_SlowBottomAlert = current_chromosome[16:20] start = (closingRate_SlowTopAlertValue + (((closingRate_MediumTopLeftAlertValue - closingRate_SlowTopAlertValue) // 2) + 1)) end = (start + (1 * (2**(len(closingRate_SlowBottomAlert))))) closingRate_SlowBottomAlertValue = transform_fuzzy( closingRate_SlowBottomAlert, 1, start, end) closingRate_MediumBottomLeftAlert = current_chromosome[20:24] end = (closingRate_MediumTopLeftAlertValue - (((closingRate_MediumTopLeftAlertValue - closingRate_SlowTopAlertValue) // 2) + 1)) start = end - (1 * (2**(len(closingRate_MediumBottomLeftAlert)))) if (end < 0): end = 0 if (start < 0): start = 0 jump = (end - start) // (2**(len(closingRate_MediumBottomLeftAlert))) closingRate_MediumBottomLeftAlertValue = transform_fuzzy( closingRate_MediumBottomLeftAlert, jump, start, end) closingRate_MediumBottomRightAlert = current_chromosome[24:28] start = (closingRate_MediumTopRightAlertValue + (((closingRate_FastTopAlertValue - closingRate_MediumTopRightAlertValue) // 2) + 1)) end = start + (1 * (2**(len(closingRate_MediumBottomRightAlert)))) closingRate_MediumBottomRightAlertValue = transform_fuzzy( closingRate_MediumBottomRightAlert, 1, start, end) closingRate_FastBottomAlert = current_chromosome[28:32] end = (closingRate_FastTopAlertValue - (((closingRate_FastTopAlertValue - closingRate_MediumTopRightAlertValue) // 2) + 1)) start = end - (1 * (2**(len(closingRate_FastBottomAlert)))) if (end < 0): end = 0 if (start < 0): start = 0 jump = (end - start) // (2**(len(closingRate_FastBottomAlert))) closingRate_FastBottomAlertValue = transform_fuzzy( closingRate_FastBottomAlert, jump, start, end) Distance_CloseTopAlert = current_chromosome[32:37] Distance_CloseTopAlertValue = transform_fuzzy( Distance_CloseTopAlert, 50, 0, (50 * (2**len(Distance_CloseTopAlert)))) Distance_FarTopAlert = current_chromosome[37:42] Distance_FarTopAlertValue = transform_fuzzy( Distance_CloseTopAlert, 50, (Distance_CloseTopAlertValue + 50), (Distance_CloseTopAlertValue + 50) + (50 * (2**len(Distance_CloseTopAlert)))) Distance_CloseBottomAlert = current_chromosome[42:47] start = (Distance_CloseTopAlertValue + (( (Distance_FarTopAlertValue - Distance_CloseTopAlertValue) // 2) + 1)) end = Distance_FarTopAlertValue jump = (end - start) // (2**(len(Distance_CloseBottomAlert))) Distance_CloseBottomAlertValue = transform_fuzzy(Distance_CloseBottomAlert, jump, start, end) Distance_FarBottomAlert = current_chromosome[47:52] end = (Distance_FarTopAlertValue - (( (Distance_FarTopAlertValue - Distance_CloseTopAlertValue) // 2) + 1)) start = Distance_CloseTopAlertValue jump = (end - start) // (2**(len(Distance_FarBottomAlert))) Distance_FarBottomAlertValue = transform_fuzzy(Distance_FarBottomAlert, jump, start, end) #Set variables for Wall feelers, heading and tracking of the agent ## heading = int(ai.selfHeadingDeg()) tracking = int(ai.selfTrackingDeg()) frontWall = ai.wallFeeler(500, heading) left45Wall = ai.wallFeeler(500, heading + 45) right45Wall = ai.wallFeeler(500, heading - 45) left90Wall = ai.wallFeeler(500, heading + 90) right90Wall = ai.wallFeeler(500, heading - 90) left135Wall = ai.wallFeeler(500, heading + 135) right135Wall = ai.wallFeeler(500, heading - 135) backWall = ai.wallFeeler(500, heading - 180) trackWall = ai.wallFeeler(500, tracking) ## Create an array that represents the closing rate of each 45 degree of the full 360 degrees surrounding the agent ## result_list = [] ## Array of the same size, but contains the risk of each direction ## risk_list = [] for i in range(8): Degree = tracking + (45 * i) Speed = ai.selfSpeed() Distance = ai.wallFeeler(10000, tracking + (45 * i)) result = Closing_Rate(Degree, tracking, Speed, Distance) result_list.append(result) ### Calculate the Fuzzy membership ### ### 1. Fuzzy Membership For Closing Rate (Speed + Tracking Involved) ### ### 2. Fuzzy Membership For Distance From Walls ### closing_rate, distance = Closing_Rate(Degree, tracking, Speed, Distance) low, medium, fast = Fuzzy_Speed( closing_rate, closingRate_SlowTopAlertValue, closingRate_SlowBottomAlertValue, closingRate_MediumBottomLeftAlertValue, closingRate_MediumTopLeftAlertValue, closingRate_MediumTopRightAlertValue, closingRate_MediumBottomRightAlertValue, closingRate_FastBottomAlertValue, closingRate_FastTopAlertValue) close, far = Fuzzy_Distance(distance, Distance_CloseTopAlertValue, Distance_CloseBottomAlertValue, Distance_FarBottomAlertValue, Distance_FarTopAlertValue) #print("close-far", close, far) risk = Fuzzy_Risk(low, medium, fast, close, far) risk_list.append(risk) ## Get the direction in deg that is most risky for the robot as well as the least risky direction ## max_risk = max(risk_list) track_risk = (tracking + (risk_list.index(max_risk) * 45) % 360) min_risk = min( risk_list ) ## Note: Biase Towards Left Side since min get the first min when risk might be equal ## ####### Getters Variable Regarding Important Information About Enemies ######## ##Find the closest ennemy## enemy = ai.lockClose() ## Get the lockheadingdeg of enemy ## head = ai.lockHeadingDeg() ## Get the dstance from enemy ## enemyDist = ai.selfLockDist() ## If the Enemy is Dead ## if (ai.selfAlive() == 0 and boolean == False): ## Calculate Fitness Current Individual ## score_previous = score score_current = ai.selfScore() fitness_value = fitness(population, count_frame, score_previous, score_current) fitness_list.append(fitness_value) ## If it went through the whole population and ready to move to next generation ## if ((loop + 1) == population_size): ## Output the fitness of population to allow user to see if learning is happening ## print("Generation:", generation) print("Agent Fitness:") print(fitness_list) print("Average Fitness:", statistics.mean(fitness_list)) print("Best Fitness:", max(fitness_list)) ## Finding the optimal chromosome to output it in data file ## string_maxChromosome = "" for chrom_max in range(chromosome_size): string_maxChromosome = string_maxChromosome + str( population[fitness_list.index( max(fitness_list))][chrom_max]) ## Formatting entire population in a big string to register it in excel file## string_population = "" for pop in range(population_size): for pop_chrom in range(chromosome_size): string_population = string_population + str( population[pop][pop_chrom]) if (pop != (population_size - 1)): string_population = string_population + "," ## Formatting entire population's fitness in a big string to register it in excel file## string_fitness = "" for fit in range(len(fitness_list)): string_fitness = string_fitness + str(fitness_list[fit]) if (fit != (len(fitness_list) - 1)): string_fitness = string_fitness + "," ## Output Data into Excel File ## titles = [ "Generation", "Average Fitness", "Best Fitness", "Population Size", "Chromosome Size", "Crossover Probability", "Mutation Probability", "Best Chromosome", "Entire Population Chromosome", "Entire Population Fitness" ] data = [ generation, statistics.mean(fitness_list), max(fitness_list), population_size, chromosome_size, crossover_prob, mutation_prob, string_maxChromosome, string_population, string_fitness ] first_time = Save_Data("Dumpster_Training_Data.xls", 0, titles, data, first_time) ## Select Population For Next Generation -- Apply Crossover & Mutation ## new_population = select(population, fitness_list) new_population = crossover(new_population, chromosome_size, population_size, crossover_prob) new_population = mutate(new_population, chromosome_size, mutation_prob) population = new_population loop = 0 count_frame = 0 generation += 1 fitness_list.clear() ### DONE -- QUIT ### if (generation == generation_size): quitAI() ## Move to the next individual in population ## else: loop += 1 count_frame = 0 boolean = True else: ## The agent is Alive ## if (ai.selfAlive() == 1): ## Get the angles on both side between tracking and heading to decide which way to turn ## dist = (heading - track_risk) % 360 dist2 = (360 - dist) % 360 ###### Production System Rules ###### ## Turning Rules ## if (dist <= 130 and dist >= 0 and ai.selfSpeed() > 0 and max_risk >= 75): ai.turnLeft(1) elif (dist2 <= 130 and dist2 >= 0 and ai.selfSpeed() > 0 and max_risk >= 75): ai.turnRight(1) elif (ai.selfSpeed() <= 10): ai.thrust(1) elif (trackWall <= 150): ai.thrust(1) ##### Bullet Avoidance Commands ##### elif (ai.shotAlert(0) >= 0 and ai.shotAlert(0) <= 50): if (ai.shotVelDir(0) != -1 and ai.angleDiff(heading, ai.shotVelDir(0)) > 0 and ai.selfSpeed() <= 5): ai.turnLeft(1) ai.thrust(1) elif (ai.shotVelDir(0) != -1 and ai.angleDiff(heading, ai.shotVelDir(0)) < 0 and ai.selfSpeed() <= 5): ai.turnRight(1) ai.thrust(1) elif (ai.shotVelDir(0) != -1 and ai.angleDiff(heading, ai.shotVelDir(0)) > 0 and ai.selfSpeed() > 5): ai.turnLeft(1) else: ai.turnRight(1) ##### Shooting Ennemy Commands ##### elif (enemyDist <= 3000 and heading > (head) and enemyDist != 0 and ai.selfSpeed() > 5): ai.turnRight(1) ai.fireShot() elif (enemyDist <= 3000 and heading < (head) and enemyDist != 0 and ai.selfSpeed() > 5): ai.turnLeft(1) ai.fireShot() ## Rules if nothing is happening ## elif (ai.selfSpeed() < 5): ai.thrust(1) else: ai.thrust(0) count_frame += 3 boolean = False
def AI_loop(): global frames, frameHistory, generation, current_chrom, population, scores, current_score print("frame", frames) #rules chrom = population[current_chrom][0] when_to_thrust_speed = convert(chrom[0:4]) front_wall_distance_thrust = convert(chrom[4:8]) * 4 back_wall_distance_thrust = convert(chrom[8:12]) * 2 track_wall_distance_thrust = convert(chrom[12:16]) * 4 left_wall_angle = convert(chrom[16:20]) * 3 right_wall_angle = convert(chrom[20:24]) * 3 back_wall_angle = convert(chrom[24:28]) * 10 left_90_wall_angle = convert(chrom[28:32]) * 6 right_90_wall_angle = convert(chrom[32:36]) * 6 left_back_wall_angle = convert(chrom[36:40]) * 9 right_back_wall_angle = convert(chrom[44:48]) * 9 fuzzy_rate = convert(chrom[48:52]) fuzzy_rate_1 = convert(chrom[52:56]) angle_diff_shoot = convert(chrom[56:60]) shot_alert_distance = convert(chrom[60:64]) * 6 rate = fuzzy_rate rate1 = fuzzy_rate_1 #Release keys ai.thrust(0) ai.turnLeft(0) ai.turnRight(0) #Set variables heading = int(ai.selfHeadingDeg()) tracking = int(ai.selfTrackingDeg()) frontWall = ai.wallFeeler(500, heading) leftWall = ai.wallFeeler(500, heading + left_wall_angle) rightWall = ai.wallFeeler(500, heading - right_wall_angle) left90Wall = ai.wallFeeler(500, heading + left_90_wall_angle) right90Wall = ai.wallFeeler(500, heading - right_90_wall_angle) leftbackWall = ai.wallFeeler(500, heading + left_back_wall_angle) rightbackWall = ai.wallFeeler(500, heading - right_back_wall_angle) trackWall = ai.wallFeeler(500, tracking) backWall = ai.wallFeeler(500, heading - back_wall_angle) #Shooting rules if ai.aimdir(0) >= 0 and -angle_diff_shoot <= ai.angleDiff( heading, ai.aimdir(0)) <= angle_diff_shoot and ai.screenEnemyX( 0) >= 0 and ai.screenEnemyY(0) >= 0 and ai.wallBetween( ai.selfX(), ai.selfY(), ai.screenEnemyX(0), ai.screenEnemyY(0)) == -1: ai.fireShot() #Turn rules if ai.aimdir(0) >= 0 and ai.angleDiff( heading, ai.aimdir(0)) > 0 and ai.wallBetween( ai.selfX(), ai.selfY(), ai.screenEnemyX(0), ai.screenEnemyY(0)) == -1: ai.turnLeft(1) #print("aim turn left") elif ai.aimdir(0) >= 0 and ai.angleDiff( heading, ai.aimdir(0)) < 0 and ai.wallBetween( ai.selfX(), ai.selfY(), ai.screenEnemyX(0), ai.screenEnemyY(0)) == -1: ai.turnRight(1) #print("aim turn right") elif left90Wall < right90Wall and minmax(10, (rate * ai.selfSpeed()), 100): ai.turnRight(1) #print("left90wall") elif right90Wall < left90Wall and minmax(10, (rate * ai.selfSpeed()), 100): ai.turnLeft(1) #print("right90wall") elif leftbackWall < minmax(5, (rate1 * ai.selfSpeed()), 50): ai.turnRight(1) #print("leftbackwall") elif rightbackWall < minmax(5, (rate1 * ai.selfSpeed()), 50): ai.turnLeft(1) #print("rightbackwall") #base case turn rules elif leftWall < rightWall: ai.turnRight(1) else: ai.turnLeft(1) #Thrust rules if ai.selfSpeed( ) <= when_to_thrust_speed and frontWall >= front_wall_distance_thrust: ai.thrust(1) #print("thrust 1") #dynamic thrust away from walls elif trackWall < track_wall_distance_thrust: ai.thrust(1) #print("thrust 2") #thrust away from back wall elif backWall < back_wall_distance_thrust: ai.thrust(1) #print("thrust 3") #Shot avoidance elif ai.shotAlert(0) >= 0 and ai.shotAlert( 0) <= shot_alert_distance and ai.shotVelDir( 0) != -1 and ai.angleDiff(heading, ai.shotVelDir(0)) > 0: #print("shotveldir turn left") ai.turnLeft(1) ai.thrust(1) elif ai.shotAlert(0) >= 0 and ai.shotAlert( 0) <= shot_alert_distance and ai.shotVelDir( 0) != -1 and ai.angleDiff(heading, ai.shotVelDir(0)) < 0: #print("shotveldir turn right") ai.turnRight(1) ai.thrust(1) #tracks frames alive if ai.selfAlive() == 1: frames += 1 elif ai.selfAlive() == 0 and frames == 0: pass else: #adds every fitness to a list to avoid the issue of xpilot score never resetting scores.append(ai.selfScore()) #base case if len(scores) < 2: current_score = scores[-1] else: current_score = scores[-1] - scores[-2] if current_score <= 0: current_score = 2 population[current_chrom][1] = (frames**2) * current_score print("fitness: ", population[current_chrom][1]) current_chrom += 1 print("current_chrom is: ", current_chrom) if current_chrom >= len(population): current_chrom = 0 print("current_chrom is: ", current_chrom) generation += 1 fitness_scores = fitness(population) #writes highest fitness agent to file if generation % 5 == 0: print("first write") current_fitness = max(fitness_scores) best_individual_index = fitness_scores.index(current_fitness) best_individual = population[best_individual_index][0] newfile = open("GA_output.txt", "a+") newfile.write("Generation: ") newfile.write("\n") newfile.write(str(generation)) newfile.write("\n") newfile.write("Best individual: ") newfile.write("\n") newfile.write(str(best_individual)) newfile.write("\n") newfile.write("Best fitness: ") newfile.write("\n") newfile.write(str(current_fitness)) newfile.write("\n") newfile.close() chrom_pair = top_individuals(population, fitness_scores) new_pop = [] new_pop += crossover(chrom_pair) while (len(new_pop) < population_size): new_pop += crossover(chrom_pair) population = [] population = new_pop #writes population to file if generation % 10 == 0: print("second write") popfile = open("GA_pop.txt", "a+") popfile.write("Generation: ") popfile.write("\n") popfile.write(str(generation)) popfile.write("\n") for i in population: popfile.write(str(i)) popfile.write("\n") popfile.write("\n") popfile.close() frames = 0
def AI_loop(self): # print("AI_LOOP") if ai.selfAlive() == 0: outputFile = open("fitness.txt", "a") # outputFile.write(str((self.totalDists/self.counter))+"\t") outputFile.write(str(int((self.fitness**1.2))) + "\t") [ print(str("%.5f" % g) + "\t", end="", file=outputFile) for g in self.chromosome ] print("\n", end="", file=outputFile) outputFile.close() # Release keys ai.thrust(0) ai.turnLeft(0) ai.turnRight(0) ai.setTurnSpeed(55) # Heuristics frontFeelerOffset = 45 perpFeelerOffset = 90 rearFeelerOffset = 135 # turnSpeedMin = 15 # learn range: 4 - 24 turnSpeedMax = 55 speedLimit = 5 # learn range: 2-6 lowSpeedLimit = 2 targetingAccuracy = 4 # 1/2 tolerance in deg for aiming accuracy shotIsDangerous = 130 # Acquire information heading = int(ai.selfHeadingDeg()) tracking = int(ai.selfTrackingDeg()) ###=== ENEMY FEELERS ===### # gets angle to enemy enemyDeg = self.angleToPointDeg( (ai.selfX(), ai.selfY()), (ai.screenEnemyX(0), ai.screenEnemyY(0))) enemyWallDistances = [] # maxAngleOffset = 90 # learn range: 30 - 120 # resolution = 5 # learn range: 2 - 10 distAngleTuples = [] # creates tuples of degrees and wallFeelers for m in (0, self.maxAngleOffset, self.resolution): distAngleTuples.append( (enemyDeg - m, ai.wallFeeler(500, int(enemyDeg - m)))) distAngleTuples.append( (enemyDeg + m, ai.wallFeeler(500, int(enemyDeg + m)))) # gets furthest feeler maxFeelerAngle = max(distAngleTuples, key=self.returnSecond) angleToOpenSpace = self.headingDiff(ai.selfHeadingDeg(), maxFeelerAngle[0]) ###=== WALL FEELERS ===### frontWall = ai.wallFeeler( self.genericFeelerDist, heading) # wall feeler for wall directly ahead leftFrontWall = ai.wallFeeler( self.genericFeelerDist, heading + frontFeelerOffset) # wall feeler for wall 45 degrees to the left rightFrontWall = ai.wallFeeler( self.genericFeelerDist, heading - frontFeelerOffset) # wall feeler for wall 45 degrees to the right leftWall = ai.wallFeeler( self.genericFeelerDist, heading + perpFeelerOffset) # wall feeler for wall 90 degrees to the left rightWall = ai.wallFeeler( self.genericFeelerDist, heading - perpFeelerOffset) # wall feeler for wall 90 degrees to the right backWall = ai.wallFeeler(self.genericFeelerDist, heading - 180) # wall feeler for wall straight back leftBackWall = ai.wallFeeler( self.genericFeelerDist, heading + rearFeelerOffset) # wall feeler for wall 135 degrees to the left rightBackWall = ai.wallFeeler( self.genericFeelerDist, heading - rearFeelerOffset) # wall feeler for wall 135 degrees to the right trackWall = ai.wallFeeler( self.genericFeelerDist, tracking) # wall in front of where ship is moving # Keep track of all the feeler distances feelers = [ frontWall, leftFrontWall, rightFrontWall, leftWall, rightWall, backWall, leftBackWall, rightBackWall, trackWall ] # Aim assist leftDir = (heading + 90) % 360 # angle 90 degrees to the left of current heading rightDir = (heading - 90 ) % 360 # angle 90 degrees to the right of current heading aimer = ai.aimdir( 0 ) # direction that the ship needs to turn to in order to face the enemy in degrees shot = ai.shotAlert( 0 ) # returns a danger rating of a shot, the smaller the number the more likely the shot is to hit the ship enemyX = ai.screenEnemyX(0) # returns the closest enemy's x-coord enemyY = ai.screenEnemyY(0) # returns the closest enemy's y-coord selfX = ai.selfX() # returns the ship's x-coord selfY = ai.selfY() # returns the ship's x-coord # Fuzzy variable declaration trackRisk = riskEval(trackWall, ai.selfSpeed()) #risk of running into trackWall frontRisk = riskEval(frontWall, ai.selfSpeed()) #risk of running into frontWall leftRisk = riskEval(leftWall, ai.selfSpeed()) #risk of running into leftWall rightRisk = riskEval(rightWall, ai.selfSpeed()) #risk of running into rightWall LFRisk = riskEval(leftFrontWall, ai.selfSpeed()) #risk of running into leftFrontWall RFRisk = riskEval(rightFrontWall, ai.selfSpeed()) #risk of running into rightFrontWall LBRisk = riskEval(leftBackWall, ai.selfSpeed()) #risk of running into leftBackWall RBRisk = riskEval(rightBackWall, ai.selfSpeed()) #risk of running into rightBackWall backRisk = riskEval(backWall, ai.selfSpeed()) #risk of running into backWall # Compress some wall feelers sTrack = self.squisher(trackWall) sLeft = self.squisher(leftFrontWall) sRight = self.squisher(rightFrontWall) sLeftStraight = self.squisher(leftWall) sRightStraight = self.squisher(rightWall) # output from neural network that tells how much to turn and which direction turn = self.trainedNeuralNetwork(sTrack, sLeft, sRight, sLeftStraight, sRightStraight) ###=== THRUST POWER ADJUSTMENT ===# # Power levels mfS = self.mfSpeed(ai.selfSpeed()) mfD = self.mfDanger(ai.shotAlert(0)) # if S is high and D is moderate or high: p1 = max(mfS[2], min(mfD[1], mfD[2])) # if S is moderate and D is moderate: p2 = max(mfS[1], mfD[1]) # if S is low and D is high: p3 = max(mfS[0], mfD[2]) # if S is moderate and D is moderate: p4 = max(mfS[1], mfD[1]) # if S is low and D is moderate: p5 = max(mfS[0], mfD[1]) # if S is high and D is low: p6 = max(mfS[2], mfD[0]) # if S is moderate and D is low: p7 = max(mfS[1], mfD[0]) # if S is low and D is low: p8 = max(mfS[0], mfD[0]) consequents = [55, 45, 55, 36, 36, 28, 24, 30] memberships = [p1, p2, p3, p4, p5, p6, p7, p8] ai.setPower(self.crispify(memberships, consequents)) if ai.enemyDistance(0) > self.lastDist and ai.enemyDistance( 0) < self.enemyClose: ai.thrust(1) elif ai.selfSpeed( ) <= 3 and frontWall >= 200: # if speed is slow and front wall is far away, thrust ai.thrust(1) elif trackWall < 60 and frontWall >= 200: # if the track wall is close, thrust ai.thrust(1) elif backWall < 20: # if the back wall is close, thrust ai.thrust(1) ###=== TURNING RULES ===### # Escape shots if shot > 0 and shot < 70: # if a shot is closeby, turn and thrust to avoid if self.angleDif(rightDir, ai.shotX(0)) < self.angleDif( leftDir, ai.shotX(0) ) or self.angleDif(rightDir, ai.shotY(0)) < self.angleDif( leftDir, ai.shotY(0) ): # if shot is coming from the right, turn away and thrust # print("Turning: avoiding shot")#debug ai.turnLeft(1) ai.thrust(1) elif self.angleDif(leftDir, ai.shotX(0)) < self.angleDif( rightDir, ai.shotX(0) ) or self.angleDif(leftDir, ai.shotY(0)) < self.angleDif( rightDir, ai.shotY(0) ): # if shot is coming from the left, turn away and shoot ------> change this shot is just a number # print("Turning: avoiding shot")#debug ai.turnRight(1) ai.thrust(1) # Turn towards unoccluded enemy elif aimer >= 0 and self.angleDif(rightDir, aimer) < self.angleDif( leftDir, aimer) and not self.enemyBehindWall( 0): # if an enemy to the right, turn and shoot it if ai.screenEnemyX(0) >= 0: enemyDeg = self.angleToPointDeg( (ai.selfX(), ai.selfY()), (ai.screenEnemyX(0), ai.screenEnemyY(0))) ai.setTurnSpeed( self.rangeMap(abs(enemyDeg), 0, 180, self.turnSpeedMin, turnSpeedMax)) else: enemyDeg = self.angleToPointDeg( (ai.selfRadarX(), ai.selfRadarY()), (ai.closestRadarX(), ai.closestRadarY())) ai.setTurnSpeed( self.rangeMap(abs(enemyDeg), 0, 180, self.turnSpeedMin, turnSpeedMax)) # print("Turning: aiming right")#debug ai.turnRight(1) elif aimer >= 0 and self.angleDif(leftDir, aimer) < self.angleDif( rightDir, aimer) and not self.enemyBehindWall( 0): # if an enemy to the left, turn and shoot it if ai.screenEnemyX(0) >= 0: enemyDeg = self.angleToPointDeg( (ai.selfX(), ai.selfY()), (ai.screenEnemyX(0), ai.screenEnemyY(0))) ai.setTurnSpeed( self.rangeMap(abs(enemyDeg), 0, 180, self.turnSpeedMin, turnSpeedMax)) else: enemyDeg = self.angleToPointDeg( (ai.selfRadarX(), ai.selfRadarY()), (ai.closestRadarX(), ai.closestRadarY())) ai.setTurnSpeed( self.rangeMap(abs(enemyDeg), 0, 180, self.turnSpeedMin, turnSpeedMax)) # print("Turning: aiming left")#debug ai.turnLeft(1) #fuzzy avoid walls ahead elif leftRisk > rightRisk and trackRisk > 0.5: # and min(feelers) < self.nearLimit: #if the left wall and track walls are close, turn right #if enemyX >=0 and enemyY >= 0 and ai.wallBetween(selfX, selfY, enemyX, enemyY) == -1: ai.turnRight(1) # print("Turning: fuzzy right")#debug elif rightRisk > leftRisk and trackRisk > 0.5: # and min(feelers) < self.nearLimit: #if the right wall and track walls are close, turn left # if enemyX >=0 and enemyY >= 0 and ai.wallBetween(selfX, selfY, enemyX, enemyY) == -1: ai.turnLeft(1) # print("Turning: fuzzy left")#debug # Turn to open space nearest the angle to the enemy elif self.enemyBehindWall(0) and min(feelers) > self.nearLimit: if angleToOpenSpace < 0: # print("Turning: open space left")#debug ai.turnLeft(1) elif angleToOpenSpace > 0: # print("Turning: open space right")#debug ai.turnRight(1) # if neural net value is not between 0.48 and 0.52 then we have to turn right or left elif not (turn >= 0.43 and turn <= 0.57): if turn < 0.43: # turn right if value is below 0.43 # print("Turning: neural net right")#debug ai.turnRight(1) elif turn > 0.57: # turn left if value is below 0.57 # print("Turning: neural net left")#debug ai.turnLeft(1) ###=== FIRING RULES ===### # Restrict firing to reasonably accurate attempts: # accurate range, enemy not behind wall and enemy close enough if self.headingDiff( heading, ai.aimdir(0)) < targetingAccuracy and not self.enemyBehindWall( 0) and ai.enemyDistance(0) < self.enemyFireDist: ai.fireShot() # print("Shot Fired")#debug # print("Firing Dist: ", self.enemyFireDist)#debug self.counter += 1 ###=== How did we die? and other Fitness Calculations ===### # Fitness function information self.totalDists += ai.enemyDistance(0) if ai.enemyDistance(0) > 0: self.currentDist = ai.enemyDistance(0) if self.currentDist < self.lastDist: self.fitness += 1 self.lastDist = self.currentDist self.fitness += 1 alive = ai.selfAlive() message = ai.scanGameMsg(1) # print(message)#debug if alive == 0: self.framesDead += 1 # print(self.framesDead, message)#debug if self.framesDead == 2: # print("dead now")#debug # Ran into wall if message.find("Beal-Morneault") != -1 and message.find( "wall") != -1: print("End of match: wall collision.") #debug self.fitness -= self.wallPenalty # Crashed into player elif message.find("crashed.") != -1: print("End of match: player collision.") #debug self.fitness -= self.crashPenalty # Killed by bullet elif message.find("Beal-Morneault was") != -1: print("End of match: killed by opponent.") #debug self.fitness -= self.killedPenalty # Killed the opponent elif message.find("by a shot from Beal-Morneault") != -1: print("End of match: killed the opponent!") #debug self.fitness += self.killerBonus else: print("End of match: enemy died.") self.fitness += (ai.selfScore() - ai.enemyScoreId(0) ) * self.scoreDiffBonusFactor ai.quitAI() else: self.framesDead = 0