Beispiel #1
0
        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
Beispiel #3
0
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
Beispiel #5
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