Beispiel #1
0
    def run(self):
        self.conn.sendto("cb".encode('utf-8'), (self.addr, self.serverport))

        while self.running:
            msg, addr = self.conn.recvfrom(2048)
            msg = msg.decode('utf-8')  # Coordinates of all players
            AllZombiePose = []

            splitted_msg = msg.split('|')
            x, y, a, _ = splitted_msg[0].split(',')
            x = float(x)
            y = float(y)
            a = float(a)
            self_pos = (x, y, a)

            for position in msg.split('|')[1:-1]:
                x, y, angle, tag = position.split(',')
                x = float(x)
                y = float(y)
                angle = float(angle)
                tag = int(tag)
                if tag == 0:
                    AllZombiePose.append((x, y, angle))

            server_map_index = int(splitted_msg[-1])
            if server_map_index != self.map_index:
                del self.world
                self.world = StaticWorld(
                    "../Maps/map_{0}.csv".format(server_map_index))
                self.map_index = server_map_index

            movement = self.dummy_escape_policy(self_pos, AllZombiePose)
            self.conn.sendto(movement.encode('utf-8'),
                             (self.addr, self.serverport))
Beispiel #2
0
    def setup_pygame(self):

        self.world = StaticWorld('../Maps/map_1.csv')

        self.screen = pygame.display.set_mode(
            (self.world.local_width * self.world.zoom,
             self.world.local_length * self.world.zoom))

        pygame.event.set_allowed(None)
        pygame.event.set_allowed([pygame.locals.QUIT, pygame.locals.KEYDOWN])
        pygame.key.set_repeat(100, 100)  #move faster
Beispiel #3
0
    def __init__(self, addr="127.0.0.1", serverport=9009):
        self.botport = random.randrange(8000, 8999)
        self.conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.conn.bind(("127.0.0.1", self.botport))
        self.addr = addr
        self.serverport = serverport

        self.read_list = [self.conn]
        self.write_list = []

        self.map_index = 0
        self.world = StaticWorld('../Maps/map_0.csv')
        self.running = True
Beispiel #4
0
    def __init__(self, port=9009, visualize = True):
        print(time.asctime(time.localtime(time.time())))

        self.listener = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # Bind to localhost - set to external ip to connect from other computers
        self.listener.bind(("127.0.0.1", port))
        self.read_list = [self.listener]
        self.write_list = []

        self.players_pose = {}
        self.players_ready = {}
        self.players_reward = {}

        self.map_index = 0
        self.world = StaticWorld('../Maps/map_0.csv')

        self.screen = pygame.display.set_mode((self.world.zoom * self.world.length, self.world.zoom * self.world.width)) \
            if sys.platform.startswith('win') and visualize else None
Beispiel #5
0
    def init_players_pose(self):
        while True:
            self.map_index = np.random.randint(0, self.map_count)
            del self.world
            self.world = StaticWorld("../Maps/map_{0}.csv".format(self.map_index))
            section_x = [(0, self.world.width // 2), (self.world.width // 2, self.world.width)][np.random.randint(0, 2)]
            section_y = [(0, self.world.length // 2), (self.world.length // 2, self.world.length)][np.random.randint(0, 2)]

            start_position = []

            for p in range(len(self.players_pose)):
                trial_cnt = 0
                while trial_cnt < 5:
                    new_pose = (np.random.randint(*section_x), np.random.randint(*section_y), np.random.random() * 2 * PI)

                    if self.world[(new_pose[0], new_pose[1])] == 1:
                        continue

                    noncollision = True
                    for existing_pose in start_position:
                        if abs(existing_pose[0] - new_pose[0]) + abs(existing_pose[1] - new_pose[1]) < 8:
                            noncollision = False
                            break

                    if noncollision:
                        start_position.append(new_pose)
                        break

                    trial_cnt += 1

                # If cannot find a suitable location for a new player, move to new map
                if trial_cnt == 5:
                    break

            # If all playerStarts are ready, break from main loop
            if len(start_position) == len(self.players_pose):
                for k in zip(self.players_pose.keys(), start_position):
                    self.players_pose[k[0]] = *(k[1]), self.players_pose[k[0]][3]
                break
Beispiel #6
0
class ZombieChasePlayerEnv(Env):
    def __init__(self):
        self.map_index = 0
        self.world = StaticWorld('Maps/map_0.csv')
        self.clientport = random.randrange(8000, 8999)
        self.conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.conn.bind(("127.0.0.1", self.clientport))
        self.addr = "127.0.0.1"
        self.serverport = 9009
        self.conn.sendto("cz".encode('utf-8'), (self.addr, self.serverport))

        self.action_space = Discrete(4)
        self.observation_space = Box(low=0,
                                     high=3,
                                     shape=(self.world.radar_length, 1),
                                     dtype=np.float)

        self.saved_self_pose = None
        self.saved_all_zombie_pose = None
        self.saved_rew = 0.0

        self.screen = None

        self.stepcount = 0

    #block if no data received
    def _fetch_pos_from_server(self):
        msg, addr = self.conn.recvfrom(2048)
        msg = msg.decode('utf-8')  # Coordinates of all players

        splitted_msg = msg.split('|')
        x, y, a, _ = splitted_msg[0].split(',')
        x = float(x)
        y = float(y)
        a = float(a)
        self_pos = (x, y, a)

        AllZombiePose = []
        for position in splitted_msg[1:-1]:
            x, y, angle, tag = position.split(',')
            x = float(x)
            y = float(y)
            angle = float(angle)
            tag = int(tag)
            AllZombiePose.append((x, y, angle, tag))

        map_index = int(splitted_msg[-1])

        return self_pos, AllZombiePose, map_index

    def _calculate_reward(self, self_pos, AllZombiePose, last_self_pose,
                          last_allZombiePose):
        if last_allZombiePose is None:
            return 0, False

        old_distance, _ = self._get_closest_bot_distance(
            last_self_pose, last_allZombiePose)
        curr_distance, _ = self._get_closest_bot_distance(
            self_pos, AllZombiePose)

        rew = 0

        # reward for approaching target
        if max(old_distance, curr_distance) < self.world.perception_grids:
            if curr_distance < old_distance:
                rew += (old_distance - curr_distance) * 0.01

        # reward for moving , weight 0.1 => 0.05
        # old_x, old_y, _ = last_self_pose
        # x, y, _ = self_pos
        # dist = np.sqrt(np.square(x - old_x) + np.square(y - old_y))
        # rew += dist * 0.01   # range[0, 0.05]

        # reward for staying near
        if curr_distance < Bot.alertRadius:
            blocked_distance = self._projection_blocking_distance(
                self_pos, AllZombiePose)
            clipped_curr_distance = max(2, curr_distance)

            rew += 2 / clipped_curr_distance * (
                curr_distance - blocked_distance) / curr_distance

        # reward for catching
        if curr_distance < 2:
            rew += 10
            return rew, True

        return rew, False

    def _projection_blocking_distance(self, self_pos, allActorPose):
        x, y, angle = self_pos
        distance, target = self._get_closest_bot_distance(
            self_pos, allActorPose)
        if distance > self.world.perception_grids or target is None:
            return 0

        target_x, target_y, _, _ = target
        me_to_target = np.asarray([target_x - x, target_y - y])
        me_to_target_unit = me_to_target / np.linalg.norm(me_to_target)

        maximum_proj_length = 0

        for actor in allActorPose:
            ax, ay, aa, atag = actor
            if atag == 0 and (x != ax or y != ay):
                actor_to_target = np.asarray([target_x - ax, target_y - ay])
                if np.linalg.norm(actor_to_target) < Bot.alertRadius:
                    actor_proj_len = np.dot(me_to_target_unit, actor_to_target)
                    if 0 < actor_proj_len < distance:
                        maximum_proj_length = max(maximum_proj_length,
                                                  actor_proj_len)
        return maximum_proj_length

    def _get_closest_bot_distance(self, self_pos, allZombiePose):
        x, y, _ = self_pos
        closest_dist_sqr = 100000000
        target_actor = None
        for actor in allZombiePose:
            ax, ay, _, atag = actor
            if atag == 1:
                dist_sqr = (ax - x)**2 + (ay - y)**2
                if dist_sqr < closest_dist_sqr:
                    closest_dist_sqr = dist_sqr
                    target_actor = actor
        return np.sqrt(closest_dist_sqr), target_actor

    #returns (obs, reward, finish)
    def step(self, action):
        cmd = None
        if action == 0:
            cmd = "uu"
        elif action == 1:
            cmd = "ui"
        elif action == 2:
            cmd = "ul"
        else:
            cmd = "ur"
        cmd += "|"
        cmd += str(self.saved_rew)

        # For Manual debugging

        # if self.saved_self_pose is not None:
        #     print(self.saved_self_pose)
        #     print(self.world.to_local_radar_obs(self.saved_self_pose, self.saved_all_zombie_pose)[:, 0])
        #     cmd = input('please input cmd')
        # else:
        #     cmd = 'ui'
        self.conn.sendto(cmd.encode('utf-8'), (self.addr, self.serverport))

        self_pos, AllZombiePos, server_map_index = self._fetch_pos_from_server(
        )
        if self.map_index != server_map_index:
            del self.world
            self.world = StaticWorld(
                "Maps/map_{0}.csv".format(server_map_index))
            self.map_index = server_map_index

        rew, done = self._calculate_reward(self_pos, AllZombiePos,
                                           self.saved_self_pose,
                                           self.saved_all_zombie_pose)
        self.saved_self_pose = self_pos
        self.saved_all_zombie_pose = AllZombiePos
        self.saved_rew = rew

        #if done or self.stepcount == 4000:
        #    self.reset()

        done = done or self.stepcount == 4000

        self.stepcount += 1

        # return self.world.to_local_obs(self_pos, AllZombiePos), rew, done, {'episode': {'r':rew, 'l':self.stepcount}}
        return self.world.to_local_radar_obs(self_pos,
                                             AllZombiePos), rew, done, {
                                                 'episode': {
                                                     'r': rew,
                                                     'l': self.stepcount
                                                 }
                                             }

    def reset(self):
        self.conn.sendto("r".encode('utf-8'), (self.addr, self.serverport))
        self_pos, AllZombiePos, server_map_index = self._fetch_pos_from_server(
        )
        if self.map_index != server_map_index:
            del self.world
            self.world = StaticWorld(
                "Maps/map_{0}.csv".format(server_map_index))
            self.map_index = server_map_index

        self.stepcount = 0
        return self.world.to_local_radar_obs(self_pos, AllZombiePos)

    metadata = {'render.modes': ['human', 'rgb_array']}

    def render(self, mode='human'):
        if self.saved_self_pose is not None:
            if mode == 'human':
                if self.screen == None:
                    self.screen = pygame.display.set_mode(
                        (self.world.local_width * self.world.zoom,
                         self.world.local_length * self.world.zoom))
                self.world.draw_local(self.screen, self.saved_self_pose,
                                      self.saved_all_zombie_pose)
                pygame.display.update()
                return
        else:
            super(ZombieChasePlayerEnv, self).render(mode=mode)

    def close(self):
        self.conn.sendto("d".encode('utf-8'), (self.addr, self.serverport))
        if self.screen is not None:
            pygame.quit()

    def seed(self, seed=None):
        return [0]
Beispiel #7
0
class GameClient(object):
    def __init__(self, addr="127.0.0.1", serverport=9009):
        self.clientport = random.randrange(8000, 8999)
        self.conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # Bind to localhost - set to external ip to connect from other computers
        self.conn.bind(("127.0.0.1", self.clientport))
        self.addr = addr
        self.serverport = serverport

        self.read_list = [self.conn]
        self.write_list = []

        self.setup_pygame()

    def setup_pygame(self):

        self.world = StaticWorld('../Maps/map_1.csv')

        self.screen = pygame.display.set_mode(
            (self.world.local_width * self.world.zoom,
             self.world.local_length * self.world.zoom))

        pygame.event.set_allowed(None)
        pygame.event.set_allowed([pygame.locals.QUIT, pygame.locals.KEYDOWN])
        pygame.key.set_repeat(100, 100)  #move faster

    def run(self):
        running = True
        clock = pygame.time.Clock()
        tickspeed = 30

        try:
            # Initialize connection to server
            self.conn.sendto("cz".encode('utf-8'),
                             (self.addr, self.serverport))
            while running:
                clock.tick(tickspeed)

                # select on specified file descriptors
                readable, writable, exceptional = (select.select(
                    self.read_list, self.write_list, [], 0))
                for f in readable:
                    if f is self.conn:
                        msg, addr = f.recvfrom(2048)
                        msg = msg.decode('utf-8')  #Coordinates of all players

                        self_pos = None
                        AllZombiePose = []

                        for position in msg.split('|')[:-1]:
                            x, y, angle, tag = position.split(',')
                            x = float(x)
                            y = float(y)
                            angle = float(angle)
                            tag = int(tag)
                            if self_pos is None:
                                self_pos = (x, y, angle)
                            AllZombiePose.append((x, y, angle, tag))

                        self.world.draw_local(self.screen, self_pos,
                                              AllZombiePose)

                        #self.world.draw_global(self.screen)
                        #self.world.draw_zombie_global(self.screen, (x, y, angle))

                for event in pygame.event.get():
                    if event.type == pygame.QUIT or event.type == pygame.locals.QUIT:
                        running = False
                        break
                    elif event.type == pygame.locals.KEYDOWN:
                        if event.key == pygame.locals.K_UP:
                            self.conn.sendto("uu".encode('utf-8'),
                                             (self.addr, self.serverport))
                        elif event.key == pygame.locals.K_LEFT:
                            self.conn.sendto("ul".encode('utf-8'),
                                             (self.addr, self.serverport))
                        elif event.key == pygame.locals.K_RIGHT:
                            self.conn.sendto("ur".encode('utf-8'),
                                             (self.addr, self.serverport))
                        pygame.event.clear(pygame.locals.KEYDOWN)

                pygame.display.update()
        finally:
            self.conn.sendto("d".encode('utf-8'), (self.addr, self.serverport))
Beispiel #8
0
class GameServer(object):
    map_count = 2

    def __init__(self, port=9009, visualize = True):
        print(time.asctime(time.localtime(time.time())))

        self.listener = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # Bind to localhost - set to external ip to connect from other computers
        self.listener.bind(("127.0.0.1", port))
        self.read_list = [self.listener]
        self.write_list = []

        self.players_pose = {}
        self.players_ready = {}
        self.players_reward = {}

        self.map_index = 0
        self.world = StaticWorld('../Maps/map_0.csv')

        self.screen = pygame.display.set_mode((self.world.zoom * self.world.length, self.world.zoom * self.world.width)) \
            if sys.platform.startswith('win') and visualize else None

    # mv is in format [l/r/u][(optional)float]
    def do_movement(self, move, player):
        pos = self.players_pose[player]
        mv = move[0]

        if len(move) > 1:
            stepsize = float(move[1:])
        else:
            if self.players_pose[player][3] == 0:
                if mv == "u":
                    stepsize = 1
                else:
                    stepsize = 0.5
            else:
                if mv == "u":
                    stepsize = 1.5
                else:
                    stepsize = 0.5

        if mv == "u":
            angle = pos[2]
            _x = pos[0] + stepsize * cos(angle)
            _y = pos[1] + stepsize * sin(angle)
            _x = np.clip(_x, 0, self.world.width)
            _y = np.clip(_y, 0, self.world.length)
            new_pos = (_x, _y, angle, pos[3])
            if self.world[new_pos[:2]] == 0:
                self.players_pose[player] = new_pos

        elif mv == "l":
            angle = pos[2] + stepsize
            if angle > 2 * PI:
                angle -= 2 * PI
            self.players_pose[player] = (pos[0], pos[1], angle, pos[3])

        elif mv == "r":
            angle = pos[2] - stepsize
            if angle < 0:
                angle += 2 * PI
            self.players_pose[player] = (pos[0], pos[1], angle, pos[3])

        else:  # stand idle
            pass

    def init_players_pose(self):
        while True:
            self.map_index = np.random.randint(0, self.map_count)
            del self.world
            self.world = StaticWorld("../Maps/map_{0}.csv".format(self.map_index))
            section_x = [(0, self.world.width // 2), (self.world.width // 2, self.world.width)][np.random.randint(0, 2)]
            section_y = [(0, self.world.length // 2), (self.world.length // 2, self.world.length)][np.random.randint(0, 2)]

            start_position = []

            for p in range(len(self.players_pose)):
                trial_cnt = 0
                while trial_cnt < 5:
                    new_pose = (np.random.randint(*section_x), np.random.randint(*section_y), np.random.random() * 2 * PI)

                    if self.world[(new_pose[0], new_pose[1])] == 1:
                        continue

                    noncollision = True
                    for existing_pose in start_position:
                        if abs(existing_pose[0] - new_pose[0]) + abs(existing_pose[1] - new_pose[1]) < 8:
                            noncollision = False
                            break

                    if noncollision:
                        start_position.append(new_pose)
                        break

                    trial_cnt += 1

                # If cannot find a suitable location for a new player, move to new map
                if trial_cnt == 5:
                    break

            # If all playerStarts are ready, break from main loop
            if len(start_position) == len(self.players_pose):
                for k in zip(self.players_pose.keys(), start_position):
                    self.players_pose[k[0]] = *(k[1]), self.players_pose[k[0]][3]
                break

    def _send_to_client(self, addr = None):
        if addr is not None:
            send = []
            for pos in list(self.players_pose):
                if pos == addr:
                    send.insert(0, "{0},{1},{2},{3}".format(*self.players_pose[pos]))
                else:
                    send.append("{0},{1},{2},{3}".format(*self.players_pose[pos]))

            send.append(str(self.map_index))
            self.listener.sendto('|'.join(send).encode('utf-8'), addr)
        else:
            for player in list(self.players_pose):
                send = []
                for pos in list(self.players_pose):
                    if player == pos:
                        send.insert(0, "{0},{1},{2},{3}".format(*self.players_pose[pos]))
                    else:
                        send.append("{0},{1},{2},{3}".format(*self.players_pose[pos]))
                send.append(str(self.map_index))
                self.listener.sendto('|'.join(send).encode('utf-8'), player)

    def run(self):
        last_updated_time = time.time()
        try:
            while True:

                if self.screen is not None:
                    if time.time() - last_updated_time > 0.03:
                        self.world.draw_global(self.screen, self.players_pose, self.players_reward)
                        pygame.display.update()
                        last_updated_time = time.time()

                    for event in pygame.event.get():
                        if event.type == pygame.QUIT or event.type == pygame.locals.QUIT:
                            pygame.quit()

                    pygame.display.update()

                readable, writable, exceptional = (
                    select.select(self.read_list, self.write_list, [])
                )
                for f in readable:
                    if f is self.listener:
                        msg, addr = f.recvfrom(2048)
                        msg = msg.decode('utf-8')
                        if len(msg) >= 1:
                            cmd = msg[0]
                            if cmd == "c":  # New Connection
                                if msg[1] == "z": # New Connection from zombie (model)
                                    self.players_pose[addr] = (0, 0, 0, 0)
                                else:
                                    self.players_pose[addr] = (0, 0, 0, 1)

                                self.players_ready[addr] = True
                                self.init_players_pose()
                            elif cmd == "u":
                                # Movement Update  ul0.3|0.5
                                # left 0.3, reward 0.5
                                if len(msg) >= 2 and addr in self.players_pose:
                                    if "|" in msg:
                                        msg_mv, msg_rew = msg[1:].split('|')
                                    else:
                                        msg_mv = msg[1:]
                                        msg_rew = None

                                    self.do_movement(msg_mv, addr)
                                    self.players_ready[addr] = True
                                    if msg_rew is not None:
                                        self.players_reward[addr] = float(msg_rew)

                            elif cmd == "d":  # Player Quitting
                                if addr in self.players_pose:
                                    del self.players_pose[addr]
                                    del self.players_ready[addr]
                            elif cmd == "r":
                                self.init_players_pose()
                                self._send_to_client(addr)
                            else:
                                print ("Unexpected: {0}".format(msg))

                            allready = all(elem for elem in self.players_ready.values())
                            if allready:
                                self._send_to_client()
                                self.players_ready = dict.fromkeys(self.players_ready, False)


        except KeyboardInterrupt as e:
            pass
Beispiel #9
0
class Bot(object):
    alertRadius = 10

    def __init__(self, addr="127.0.0.1", serverport=9009):
        self.botport = random.randrange(8000, 8999)
        self.conn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.conn.bind(("127.0.0.1", self.botport))
        self.addr = addr
        self.serverport = serverport

        self.read_list = [self.conn]
        self.write_list = []

        self.map_index = 0
        self.world = StaticWorld('../Maps/map_0.csv')
        self.running = True

    def run(self):
        self.conn.sendto("cb".encode('utf-8'), (self.addr, self.serverport))

        while self.running:
            msg, addr = self.conn.recvfrom(2048)
            msg = msg.decode('utf-8')  # Coordinates of all players
            AllZombiePose = []

            splitted_msg = msg.split('|')
            x, y, a, _ = splitted_msg[0].split(',')
            x = float(x)
            y = float(y)
            a = float(a)
            self_pos = (x, y, a)

            for position in msg.split('|')[1:-1]:
                x, y, angle, tag = position.split(',')
                x = float(x)
                y = float(y)
                angle = float(angle)
                tag = int(tag)
                if tag == 0:
                    AllZombiePose.append((x, y, angle))

            server_map_index = int(splitted_msg[-1])
            if server_map_index != self.map_index:
                del self.world
                self.world = StaticWorld(
                    "../Maps/map_{0}.csv".format(server_map_index))
                self.map_index = server_map_index

            movement = self.dummy_escape_policy(self_pos, AllZombiePose)
            self.conn.sendto(movement.encode('utf-8'),
                             (self.addr, self.serverport))

    def dummy_escape_policy(self, self_pos, zombies):
        dir_score = [0 for _ in range(24)]
        x, y, angle = self_pos
        zombie_in_sight = False
        for z in zombies:
            zx, zy, zangle = z
            relative_angle = degrees(atan2(zy - y, zx - x))
            if relative_angle < 0:
                relative_angle += 360  #[0, 360]
            center_sector = round(relative_angle / 15)
            z_distance_sqr = (zx - x)**2 + (zy - y)**2

            for sector in range(center_sector - 11, center_sector + 11):
                dir_score[sector % 24] -= 1 / (
                    (abs(sector - center_sector) + 1) * z_distance_sqr)  #score

            if z_distance_sqr < Bot.alertRadius * Bot.alertRadius:
                zombie_in_sight = True
        input()
        if not zombie_in_sight:
            return "ui"

        for s in range(24):
            wangle = s * 15
            wallDistance = self.world.rayCastWall((x, y), wangle)

            if wallDistance < 2:
                dir_score[s] = -99999
            else:
                dir_score[s] -= 1 / self.world.rayCastWall((x, y), wangle)**2

        now_heading_index = round(degrees(angle) / 15) % 24

        best_index = dir_score.index(max(dir_score))

        if dir_score[now_heading_index] == max(dir_score):
            return "uu"
        else:
            # if best_index - now_heading_index < -12 or 0 < best_index - now_heading_index < 12:
            #     return "ul"
            # else:
            #     return "ur"
            angle_diff_rad = radians(abs(best_index - now_heading_index) * 15)
            if best_index > now_heading_index:
                return "ul" + str(angle_diff_rad)
            else:
                return "ur" + str(angle_diff_rad)