All pastes #2053718 Raw Edit

Anonymous

public text v1 · immutable
#2053718 ·published 2011-05-04 06:50 UTC
rendered paste body
# Phil Fritzsche
# Gary Parker
# Connecticut College Computer Science

import math
import sys
import thread
import threading
import time

import xpai

sys.setcheckinterval(0)

MAX_TURN = 20

#chromosome = '100100111100011000101100000011111101101001010100000000100100000110011110'
chromosome = '000000000000000000000000000000000000000000000000000000000000000000000000'

class Struct(dict):
    """A dictionary whose values can also be accessed as attributes."""
    def __init__(self, **kwargs):
        self.update(kwargs)

    def __getattr__(self, name):
        """Retrieves the value for the given name, if it exists. Returns
        None if it does not."""
        if name in self:
            return self[name]

    def __setattr__(self, name, value):
        """Sets the value for the given name to the given value."""
        self[name] = value


def gene_to_num(gene):
   dec_num = 0
   for i in gene:
       dec_num = (dec_num << 1) | int(i)
   return dec_num


gene = Struct()
def load_gene(chromosome):
    xpai.talk(str(chromosome))
    global gene
    gene = Struct(
        span=gene_to_num(chromosome[0:4]),
        offset_inc=gene_to_num(chromosome[4:8]) + 1,
        samespread=gene_to_num(chromosome[8:12]),
        wall_span1=gene_to_num(chromosome[12:16]) * 4,
        wall_span2=gene_to_num(chromosome[16:20]) * 4,
        vd_bullet_dist=gene_to_num(chromosome[20:24]) * 4,
        close_wall_speed=gene_to_num(chromosome[24:28]) * 2,
        c_angle_before_thrust=gene_to_num(chromosome[28:32]) * 10,
        d_bullet_dist=(gene_to_num(chromosome[32:36]) * 4) + \
            (gene_to_num(chromosome[20:24]) * 4),
        medium_wall_speed=gene_to_num(chromosome[36:40]) * 4,
        m_angle_before_thrust=gene_to_num(chromosome[40:44]) * 10,
        wall_avoid_angle=gene_to_num(chromosome[44:48]),
        screen_thrust_speed=gene_to_num(chromosome[48:52]),
        radar_no_thrust_speed=gene_to_num(chromosome[52:56]),
        ship_error_to_shoot=gene_to_num(chromosome[56:60]) * 2,
        radar_error_to_shoot=gene_to_num(chromosome[60:64]) * 2,
        vd_dodge_bullet_angle=gene_to_num(chromosome[64:68]) * 10,
        d_dodge_bullet_angle=gene_to_num(chromosome[68:72]) * 10
    )


def wall_feeler(range, degree):
    """Checks for walls within the given range at the given degree from the
    ship's current position. Uses absolute scale for degrees."""
    delta_x = xpai.self_x() + range * math.cos(math.radians(degree))
    delta_y = xpai.self_y() + range * math.sin(math.radians(degree))
    res = xpai.wallbetween(xpai.self_x(), xpai.self_y(), delta_x, delta_y)
    return res == -1 and range or res


def is_shot_behind_wall(n, span):
    c1 = bool(wall_feeler(
        xpai.shot_dist(n), xpai.shot_xdir(n)) < xpai.shot_dist(n))
    c2 = bool(wall_feeler(
        xpai.shot_dist(n), xpai.angleadd(
            xpai.shot_xdir(n), span)) < xpai.shot_dist(n))
    c3 = bool(wall_feeler(
        xpai.shot_dist(n), xpai.angleadd(
            xpai.shot_xdir(n), -span)) < xpai.shot_dist(n))
    return c1 and c2 and c3


def is_ship_behind_wall(n):
    return bool(wall_feeler(
        xpai.ship_dist(n), xpai.ship_xdir(n)) < xpai.ship_dist(n))


def is_radar_ship_behind_wall(n):
    return bool(wall_feeler(
        xpai.radar_dist(n), xpai.radar_xdir(n)) < xpai.radar_dist(n))


def wall_avoid_turn_dir_ship(n, offset_inc):
    range = xpai.ship_dist(n)
    degree = xpai.ship_xdir(n)
    return wall_avoid_turn_dir_helper(range, degree, 0, offset_inc)


def wall_avoid_turn_dir_radar(n, offset_inc):
    range = xpai.radar_dist(n)
    degree = xpai.radar_xdir(n)
    return wall_avoid_turn_dir_helper(range, degree, 0, offset_inc)


def wall_avoid_turn_dir_helper(rng, deg, os, os_inc):
    if os > 180:
        return -1000
    elif wall_feeler(rng, deg + os) == rng:
        return deg + os
    elif wall_feeler(rng, deg - os) == rng:
        return deg - os
    return wall_avoid_turn_dir_helper(rng, deg, os + os_inc, os_inc)


def screen_enemy_num(n): 
    """Returns the number of the nearest enemy on screen, or -1 if no
    enemy is currently on screen."""
    if xpai.ship_x(n) == -1:
        return -1
    elif xpai.teamplay() == 1 and xpai.self_team() != xpai.ship_team(n):
        return n
    return screen_enemy_num(n + 1)

def screen_enemy_num2(n, first):
    if first < 0:
        return -1
    elif xpai.ship_x(n) == -1:
        return -1
    elif (n != first and xpai.teamplay == 1 and
          xpai.self_team() != xpai.ship_team(n)):
        return n
    return screen_enemy_num(n + 1)

def radar_enemy_num2(n, first):
    if first < 0:
        return -1
    elif xpai.radar_x(n) == -1:
        return -1
    elif n != first and xpai.radar_xdir(n) != -1:
        return n
    return radar_enemy_num(n + 1)


def is_same(x, y, spread):
    return abs(x - y) <= spread


def radar_enemy_num(n):
    """Returns the number of the nearest enemy on radar, or -1 if no
    enemy currently exists on radar."""
    if xpai.radar_x(n) == -1:
        return -1
    elif xpai.radar_xdir(n) != -1:
        return n
    return radar_enemy_num(n + 1)


def change_heading(dir):
    """Turns the ship relative to its heading."""
    xpai.self_turn(xpai.anglediff(xpai.self_heading(), dir))


current_score = xpai.self_score()
reset_flag = False
frames = 0
kills = 0
final_fitness = 0
start_time = time.time()
pre_life = True
is_done = threading.Event()

def reset_all():
    global current_score
    global frames
    global kills
    global final_fitness
    global is_done
    global reset_flag
    global start_time
    current_score = xpai.self_score()
    frames = 0
    kills = 0
    final_fitness = 0
    start_time = time.time()
    is_done.clear()
    reset_flag = False

def ai_main():
    """Main function for the script; called once every frame of the game."""
    global is_done
    global pre_life
    if pre_life and not xpai.self_alive():
        return
    pre_life = False

    global current_score
    if xpai.self_score() > current_score and not is_done.isSet():
        global kills
        kills += 1
    elif xpai.self_score() < current_score and not is_done.isSet():
        global start_time
        start_time -= 20
    current_score = xpai.self_score()

    #print 'is_done: %r' % is_done
    #print 'final_fitness: %r' % final_fitness
    #print 'kills: %r' % kills
    #print 'frames: %r' % frames
    if xpai.self_alive():
        global frames
        frames += 1

        ship_num = screen_enemy_num(0)
        ship_num2 = screen_enemy_num2(0, ship_num)
        radar_ship_num = radar_enemy_num(0)
        radar_ship_num2 = radar_enemy_num2(0, radar_ship_num)

        wf_r1 = wall_feeler(600, xpai.angleadd(
            xpai.self_track(), -gene.wall_span1))
        wf_l1 = wall_feeler(600, xpai.angleadd(
            xpai.self_track(), gene.wall_span1))
        wf_r2 = wall_feeler(600, xpai.angleadd(
            xpai.self_track(), -gene.wall_span2))
        wf_l2 = wall_feeler(600, xpai.angleadd(
            xpai.self_track(), gene.wall_span2))

        # Dodge bullet if very close
        #print 'alive'
        if (xpai.shot_alert(0) > -1 and
            xpai.shot_alert(0) < gene.vd_bullet_dist and
            not is_shot_behind_wall(0, gene.span)):
            #print 'bullet vd'

            added_ang = xpai.angleadd(xpai.shot_idir(0),
                                      gene.vd_dodge_bullet_angle)
            change_heading(added_ang)
            xpai.self_thrust(1)

        elif (xpai.shot_alert(1) > -1 and
              xpai.shot_alert(1) < gene.vd_bullet_dist and
              not is_shot_behind_wall(1, gene.span)):
            #print 'bullet2 vd'

            added_ang = xpai.angleadd(xpai.shot_idir(1),
                                      gene.vd_dodge_bullet_angle)
            change_heading(added_ang)
            xpai.self_thrust(1)

        # Two wall feelers are close
        elif (is_same(wf_r1, wf_l1, gene.samespread) and
              wf_r1 < gene.close_wall_speed * xpai.self_vel() and
              xpai.self_vel() > 1):
            #print 'both wall feelers close'

            turn_amt = xpai.angleadd(180, xpai.self_track())
            change_heading(turn_amt)
            if (abs(xpai.anglediff(xpai.self_heading(), turn_amt)) <
                gene.c_angle_before_thrust):
                xpai.self_thrust(1)
        
        # Right wall feeler is closer than the left
        elif (wf_r1 < wf_l1 and
              wf_r1 < gene.close_wall_speed * xpai.self_vel() and
              xpai.self_vel() > 1):
            #print 'right wall feeler close'  

            turn_amt = xpai.angleadd(180, xpai.angleadd(
                -gene.wall_span1, xpai.self_track()))
            change_heading(turn_amt)
            if (abs(xpai.anglediff(xpai.self_heading(), turn_amt)) <
                gene.c_angle_before_thrust):
                xpai.self_thrust(1)
 
        # Left wall feeler is closer than the right 
        elif (wf_r1 > wf_l1 and
              wf_l1 < gene.close_wall_speed * xpai.self_vel() and
              xpai.self_vel() > 1):
            #print 'left wall feeler close'

            turn_amt = xpai.angleadd(180, xpai.angleadd(
                gene.wall_span1, xpai.self_track()))
            change_heading(turn_amt)
            if (abs(xpai.anglediff(xpai.self_heading(), turn_amt)) <
                gene.c_angle_before_thrust):
                xpai.self_thrust(1)

        # Dodge bullet if close [but not very]
        elif (xpai.shot_alert(0) > -1 and
              xpai.shot_alert(0) < gene.d_bullet_dist and
              not is_shot_behind_wall(0, gene.span)):
            #print 'bullet d'

            added_ang = xpai.angleadd(xpai.shot_idir(0),
                                      gene.d_dodge_bullet_angle)
            change_heading(added_ang)
            xpai.self_thrust(1)

        elif (xpai.shot_alert(1) > -1 and
              xpai.shot_alert(1) < gene.d_bullet_dist and
              not is_shot_behind_wall(1, gene.span)):
            #print 'bullet2 d'

            added_ang = xpai.angleadd(xpai.shot_idir(1),
                                      gene.d_dodge_bullet_angle)
            change_heading(added_ang)
            xpai.self_thrust(1)

        # Two wall feelers are at medium distance
        elif (is_same(wf_r2, wf_l2, gene.samespread) and
              wf_r2 < gene.medium_wall_speed * xpai.self_vel() and
              xpai.self_vel() > 1):
            #print 'both wall feelers medium'

            turn_amt = xpai.angleadd(180, xpai.self_track())
            change_heading(turn_amt)
            if (abs(xpai.anglediff(xpai.self_heading(), turn_amt)) <
                gene.m_angle_before_thrust):
                xpai.self_thrust(1)

        # Right wall feeler is closer than the left
        elif (wf_r2 < wf_l2 and
              wf_r2 < gene.medium_wall_speed * xpai.self_vel() and
              xpai.self_vel() > 1):
            #print 'right wall feeler medium'

            turn_amt = xpai.angleadd(180, xpai.angleadd(
                -gene.wall_span2, xpai.self_track()))
            change_heading(turn_amt)
            if (abs(xpai.anglediff(xpai.self_heading(), turn_amt)) <
                gene.m_angle_before_thrust):
                xpai.self_thrust(1)

        # Left wall feeler is closer than the right
        elif (wf_l2 < wf_r2 and
              wf_l2 < gene.medium_wall_speed * xpai.self_vel() and
              xpai.self_vel() > 1):
            #print 'left wall feeler medium'

            turn_amt = xpai.angleadd(180, xpai.angleadd(
                gene.wall_span2, xpai.self_track()))
            change_heading(turn_amt)
            if (abs(xpai.anglediff(xpai.self_heading(), turn_amt)) <
                gene.m_angle_before_thrust):
                xpai.self_thrust(1)

        # Turn towards nearest enemy ship on screen
        elif ship_num > -1 and not is_ship_behind_wall(ship_num):
            #print 'turn towards nearest enemy ship on screen'
            change_heading(xpai.ship_aimdir(ship_num))

        # Turn towards second nearest enemy ship on screen
        elif ship_num2 > -1 and not is_ship_behind_wall(ship_num2):
            #print 'turn towards nearest enemy ship2 on screen'
            change_heading(xpai.ship_aimdir(ship_num2))

        # Turn, thrust towards nearest enemy
        elif (ship_num > -1 and
              not wall_avoid_turn_dir_ship(ship_num, gene.offset_inc) == -1000):
            #print 'turn and thrust towards nearest enemy'
            turn_dir = wall_avoid_turn_dir_ship(ship_num, gene.offset_inc)
            turn_amt = xpai.anglediff(xpai.self_heading(), turn_dir)
            xpai.self_turn(turn_amt)
            if (abs(turn_amt) < gene.wall_avoid_angle and
                xpai.self_vel() < gene.screen_thrust_speed):
                xpai.self_thrust(1)

        # Turn, thrust towards nearest enemy
        elif (ship_num2 > -1 and
              not wall_avoid_turn_dir_ship(ship_num2, gene.offset_inc) == -1000):
            #print 'turn and thrust towards nearest enemy2'
            turn_dir = wall_avoid_turn_dir_ship(ship_num2, gene.offset_inc)
            turn_amt = xpai.anglediff(xpai.self_heading(), turn_dir)
            xpai.self_turn(turn_amt)
            if (abs(turn_amt) < gene.wall_avoid_angle and
                xpai.self_vel() < gene.screen_thrust_speed):
                xpai.self_thrust(1)

        # Turn to radar ship, thrust if not going too fast. Otherwise, shoot.
        elif (radar_ship_num > -1 and
              not is_radar_ship_behind_wall(radar_ship_num) and
              xpai.self_vel() > gene.radar_no_thrust_speed):
            #print 'turn to radar ship and thrust if not going too fast 1'
            # enemy 0 on radar, no wall and currently moving fast
            change_heading(xpai.radar_xdir(radar_ship_num))

        elif (radar_ship_num > -1 and
              not is_radar_ship_behind_wall(radar_ship_num)):
            #print 'turn to radar ship and thrust if not going too fast 2'
            # enemy 0 on radar, no wall, and not currently moving fast
            change_heading(xpai.radar_xdir(radar_ship_num))
            xpai.self_thrust(1)

        elif (radar_ship_num2 > -1 and
              not is_radar_ship_behind_wall(radar_ship_num2) and
              xpai.self_vel() > gene.radar_no_thrust_speed):
            #print 'turn to radar ship and thrust if not going too fast 3'
            # enemy 1 is on radar, no wall, and currently moving fast
            change_heading(radar_ship_num2)

        elif (radar_ship_num2 > -1 and
              not is_radar_ship_behind_wall(radar_ship_num2)):
            #print 'turn to radar ship and thrust if not going too fast 4'
            # enemy 1 on radar, no wall, and not currently moving fast
            change_heading(xpai.radar_xdir(radar_ship_num2))
            xpai.self_thrust(1)

        elif (radar_ship_num > -1 and
              wall_avoid_turn_dir_radar(radar_ship_num, gene.offset_inc) != -1000):
            #print 'turn to radar ship and thrust if not going too fast 5'
            # enemy 0 on radar and behind wall
            turn_dir = wall_avoid_turn_dir_radar(radar_ship_num, gene.offset_inc)
            turn_amt = xpai.anglediff(xpai.self_heading(), turn_dir)
            xpai.self_turn(turn_amt)
            if abs(turn_amt) < 5 and xpai.self_vel() < 20:
                xpai.self_thrust(1)


        angle_to_ship_diff = xpai.anglediff(
            xpai.self_heading(), xpai.ship_aimdir(ship_num))
        shoot_cond1 = bool(
            ship_num > -1 and
            abs(angle_to_ship_diff) < gene.ship_error_to_shoot and
            not is_ship_behind_wall(ship_num))
        #print 'shoot cond1'

        angle_to_ship2_diff = xpai.anglediff(
            xpai.self_heading(), xpai.ship_aimdir(ship_num2))
        shoot_cond2 = bool(
            ship_num2 > -1 and
            abs(angle_to_ship2_diff) < gene.ship_error_to_shoot and
            not is_ship_behind_wall(ship_num2))
        #print 'shoot cond2'

        angle_to_rship_diff = xpai.anglediff(
            xpai.self_heading(), xpai.radar_xdir(radar_ship_num))
        shoot_cond3 = bool(
            radar_ship_num > -1 and
            abs(angle_to_rship_diff) < gene.radar_error_to_shoot and
            not is_radar_ship_behind_wall(radar_ship_num))
        #print 'shoot cond3'

        angle_to_rship2_diff = xpai.anglediff(
            xpai.self_heading(), xpai.radar_xdir(radar_ship_num2))
        shoot_cond4 = bool(
            radar_ship_num2 > -1 and
            abs(angle_to_rship2_diff) < gene.radar_error_to_shoot and
            not is_radar_ship_behind_wall(radar_ship_num2))
        #print 'shoot cond4'

        if shoot_cond1 or shoot_cond2 or shoot_cond3 or shoot_cond4:
            #print 'shooting'
            xpai.self_shoot(1)
        #print 'after shooting'
    elif reset_flag:
        reset_all()
        pre_life = True
    elif not is_done.isSet() and abs(time.time() - start_time) > 120:
        global final_fitness
        final_fitness = frames + (1000 * kills)
        pre_life = True
        is_done.set()
    else:
        xpai.talk(str(frames))
        xpai.talk(str(abs(time.time() - start_time)))
        pre_life = True

def set_reset(chrom):
    global reset_flag
    global is_done
    load_gene(chrom)
    reset_flag = True
    is_done.clear()

def get_fitness():
    xpai.talk(str(final_fitness))
    return final_fitness

def launch(fps):
    # Initialize XPilot
    xpai.set_AImain(ai_main)
    xpai.setmaxturn(MAX_TURN)
    xpai.setargs('-join localhost -port 45%s -name Expert' % fps)
    load_gene(chromosome)
    thread.start_new_thread(xpai.launch, ())