示例#1
0
def run_dijkstra(graph, source, target):
    """Dijkstra's shortest path algorithm"""
    queue = PriorityQueue()
    dist = {source: 0}
    prev = {}

    for vertex in graph:
        if vertex != source:
            dist[vertex] = float("inf")
        queue.insert(vertex, dist[vertex])

    while not queue.is_empty():
        u_dist, u = queue.pop()
        u_node = graph[u]

        if u == target:
            break

        for v in u_node['linkTo']:
            if queue.is_node_in_queue(v):
                alt = dist[u] + \
                    calc_distance(int(u_node['x']), int(u_node['y']),
                                  int(graph[v]['x']), int(graph[v]['y']))
                if alt < dist[v]:
                    dist[v] = alt
                    prev[v] = u
                    queue.insert(v, alt)

    path = []
    curr = target
    while curr in prev:
        path.append(curr)
        curr = prev[curr]
    path.append(source)
    return path[::-1]
示例#2
0
def run_dijkstra(graph, source, target):
    """Dijkstra's shortest path algorithm"""
    queue = PriorityQueue()
    dist = {source: 0}
    prev = {}

    for vertex in graph:
        if vertex != source:
            dist[vertex] = float("inf")
        queue.insert(vertex, dist[vertex])

    while not queue.is_empty():
        u_dist, u = queue.pop()
        u_node = graph[u]

        if u == target:
            break

        for v in u_node['linkTo']:
            if queue.is_node_in_queue(v):
                alt = dist[u] + \
                    calc_distance(int(u_node['x']), int(u_node['y']),
                                  int(graph[v]['x']), int(graph[v]['y']))
                if alt < dist[v]:
                    dist[v] = alt
                    prev[v] = u
                    queue.insert(v, alt)

    path = []
    curr = target
    while curr in prev:
        path.append(curr)
        curr = prev[curr]
    path.append(source)
    return path[::-1]
示例#3
0
def Dijkstra(G, src):
    #initialization
    dist = {}
    #   prev = {}

    Q = PriorityQueue()
    #   print(g["home"].keys())

    #출발노드 s는 자신까지의 거리가 0이고 자신의 predecessor
    dist[src] = 0
    #   prev[s] = None

    #다른 노드들은 모두 거리를 infinity로 설정하고 predecessor는 일단 None으로 설정하고
    '''for n in g:
        dist[n[0]] = float('inf')
        prev[n[0]] = None
        dist[n[1]] = float('inf')
        prev[n[1]] = None
    '''
    #그러면서 PQ에다가 노드들을 넣어줍니다.
    for node in G.keys():
        if node != src:
            dist[node] = float('inf')
            #prev[n] = None
        '''
        if n in g[s].keys():
            dist[n] = float('inf')
            prev[n] = None
        '''
        Q.insert(dist[node], node)  # n이 우선순위 dist가 value
    #PQ가 빌때까지 계속 루프를 돌면서,
    while Q.size() > 0:
        p, u = Q.pop()  #현재까지 가장 짧은 거리를 갖고 있는 노드를 pop

        #꺼낸 노드의 각 이웃들까지의 거리를 현재 자신까지의 minimum cost와 더한 후
        #이웃들이 가지고 있는 거리보다 작으면 이것으로 업데이트 시키고 다시 PQ에 넣거나 update합니다
        #pd insert 기능에 포함되어 있다고 한다.
        '''for v in g[u].keys():
#           alt = dist[u] + g[u][v].get('weight',1)
            alt = dist[u] + g[u][v]
            if alt < dist[v]:
                dist[v] = alt
                prev[v] = u
                Q.insert(dist[v],v)       #for v in g.neighbors(u):
        '''
        for v in G[u].keys():
            #alt = dist[u] + g[u][v].get('weight',1)
            alt = dist[u] + G[u][v]
            if alt < dist[v]:
                dist[v] = alt
                Q.insert(dist[v], v)

    return dist
示例#4
0
文件: ai.py 项目: Derekmod/TBAI
    def getMove(self, state, nslaves=1):
        '''Make the AI make a move.
        Args:
            state: <State>
        Returns:
            <Move> in the move_list of 'state'
        '''
        hash_fn = lambda node: node.state.compressed  #TODO remove
        #value_fn = lambda node: node._global_log_prob #TODO strengthen
        value_fn = lambda node: node.depth
        pq = PriorityQueue(hash_fn, value_fn)

        player_info = PlayerInfo(turn=state.player_turn,
                                 prob_power=0.1,
                                 max_uncertainty=self._max_uncertainty,
                                 q=self.q_choice)
        root = StateNode(state, player_info)
        pq.add(root)

        redundant = dict()

        slave_procs = []
        slave_pipes = []
        for pidx in range(nslaves):
            slave_pipe, pipe = Pipe()
            proc = Process(target=AIPlayer.evalStates, args=(self, pipe))

            slave_procs += [proc]
            slave_pipes += [slave_pipe]

            proc.start()

        nchecked = 0
        target_slave = 0
        flying_nodes = 0
        while nchecked < self._max_states and len(
                pq) + flying_nodes:  #terminal condition
            if len(pq):
                next = pq.pop()
                next_state = next.state
                compressed = next_state.compressed
                if compressed not in redundant:
                    redundant[compressed] = next
                else:
                    original = redundant[compressed]
                    #next = redundant[compressed]
                    #for new_node in next.parent._addChild():
                    for new_node in next.reportRedundant(original):
                        pq.add(new_node)
                    continue

                pipe = slave_pipes[target_slave]
                pipe.send(next_state)
                flying_nodes += 1
                nchecked += 1

            for pipe in slave_pipes:
                if pipe.poll():
                    try:
                        obj = pipe.recv()
                        flying_nodes -= 1
                        if not obj:
                            print('ERROR: slave closed before master [E1]')
                        heur_bundle, compressed = obj
                        new_nodes = redundant[compressed].check(heur_bundle)
                        for new_node in new_nodes:
                            pq.add(new_node)
                    except EOFError:
                        print('ERROR: slave closed before master [E2]')

        for pipe in slave_pipes:
            pipe.send(None)

        active_pipes = copy.copy(slave_pipes)
        while active_pipes:
            for pipe in active_pipes:
                try:
                    obj = pipe.recv()
                    if not obj:
                        active_pipes.remove(pipe)
                        continue
                    heur_bundle, compressed = obj
                    redundant[compressed].check(heur_bundle)
                except EOFError:
                    pipes.remove(pipe)

        if self.train_iterations:
            X = []
            Y = []
            while len(player_info.training_nodes):
                _, training_state, value, err = player_info.training_nodes.pop(
                )
                #value = node._expected_value
                #err = (node._expected_value - node._self_value) ** 2

                x = training_state.features()
                y = torch.FloatTensor([value, err])

                X += [x]
                Y += [y]

            if self._model:
                self.train(X, Y)

        #cleanNode(root)
        #for child in root.children:
        #    child.recalcValue(verbose=True)

        # find best move
        # PENDING: add randomness
        best_node = None
        moves = []
        uprobs = []
        for node in root.children:
            #print(node.value, node._self_value # TODO re add
            #print(node.state.toString()) # TODO re add
            if not best_node or (node.value - best_node.value) * (
                    2 * state.player_turn - 1) > 0:
                best_node = node

            moves += [node.move]
            uprobs += [
                get_uprob(get_utility(node.value, state.player_turn),
                          node.uncertainty, player_info.q)
            ]

        if self.train_iterations > 0:
            prob_scale = random.uniform(0, sum(uprobs))
            for i in range(len(uprobs)):
                prob_scale -= uprobs[i]
                if prob_scale <= 0:
                    return moves[i]

        #return state.moves[0] #TEMP
        return best_node.move
示例#5
0
class GameLevel:
    def __init__(self, dm, level_num, length, width, category):
        self.dm = dm
        self.eventQueue = PriorityQueue()
        self.cameras = {}
        self.light_sources = []
        self.security_lockdown = False
        self.upStairs = ''
        self.downStairs = ''
        self.map = []
        self.lvl_length = length
        self.lvl_width = width
        self.level_num = level_num
        self.category = category
        self.initialize_dungeon_locs()
        self.monsters = []
        self.melee = MeleeResolver(dm, dm.dui)
        self.subnet_nodes = []
        self.cameras_active = random() < 0.8
        self.security_active = True
    
    # It would be nice if instead of alerting all monsters within a 
    # certain radius, if the sound were blocked by walls, muffled by
    # doors etc.  A flood-fill algorithm of some sort?
    def handle_stealth_check(self, player):
        _loudness = do_d10_roll(1,1)
        _roll = player.stealth_roll()
        _roll = int(round(_roll / 10.0))
        _volume = _loudness - _roll
        if _roll < 1:
            _roll = 1

        _radius = 6 - _roll
        if _radius < 1:
            _radius = 1
        
        _noise = Noise(_volume, player, player.row, player.col, 'walking')
        self.monsters_react_to_noise(_radius, _noise)
        
    def monsters_react_to_noise(self, radius, noise):
        for _m in self.monsters:
            _d = calc_distance(noise.row, noise.col, _m.row, _m.col)
            if _d <= radius:
                _spotted = _m.react_to_noise(noise)
                # I can later use success or failure of action to count
                # as practice toward the player improving his skills
                # ie., if noise.description == 'walking'...
                
    # is a location a valid square in the current map
    def in_bounds(self,r,c):
        return r >= 0 and r < self.lvl_length and c >= 0 and c < self.lvl_width

    def is_cyberspace(self):
        return False
        
    def add_item_to_sqr(self, row, col, item):
        if not hasattr(self.dungeon_loc[row][col], 'item_stack'):
            setattr(self.dungeon_loc[row][col], 'item_stack', ItemStack())
            
        self.dungeon_loc[row][col].item_stack.append(item)
    
    def size_of_item_stack(self, row, col):
        _loc = self.dungeon_loc[row][col]
        if not hasattr(_loc, 'item_stack'): return 0
        
        return len(_loc.item_stack)
        
    def add_light_source(self, light_source):
        _sc = Shadowcaster(self.dm, light_source.radius, light_source.row, light_source.col)
        light_source.illuminates = _sc.calc_visible_list()
        light_source.illuminates[(light_source.row, light_source.col)] = 0
        self.light_sources.append(light_source)

    def clear_bresenham_points(self, row, col, radius):
        _pts = []
        x = radius
        y = 0
        error = 0
        sqrx_inc = 2 * radius - 1
        sqry_inc = 1
    
        while (y <= x):
            if self.is_clear(row+y, col+x): _pts.append((row+y, col+x))
            if self.is_clear(row-y, col+x): _pts.append((row-y, col+x))
            if self.is_clear(row+y, col-x): _pts.append((row+y, col-x))
            if self.is_clear(row-y, col-x): _pts.append((row-y, col-x))
            if self.is_clear(row+x, col+y): _pts.append((row+x, col+y))
            if self.is_clear(row-x, col+y): _pts.append((row-x, col+y))
            if self.is_clear(row+x, col-y): _pts.append((row+x, col-y))
            if self.is_clear(row-x, col-y): _pts.append((row-x, col-y))

            y += 1
            error += sqry_inc
            sqry_inc = sqry_inc + 2
            if error > x:
                x -= 1
                error -= sqrx_inc
                sqrx_inc -= 2
    
        return _pts
        
    def disable_lifts(self):
        if self.upStairs != '':
            _up = self.map[self.upStairs[0]][self.upStairs[1]]
            _up.activated = False
        if self.downStairs != '':
            _down = self.map[self.downStairs[0]][self.downStairs[1]]
            _down.activated = False 

    def douse_squares(self, ls):
        self.eventQueue.pluck(('extinguish', ls.row, ls.col, ls))
        self.light_sources.remove(ls)
        for _d in ls.illuminates:
            self.dungeon_loc[_d[0]][_d[1]].lit = False

    def end_of_turn(self):
        self.dm.meatspace_end_of_turn_cleanup()
        
        if self.dm.turn % 20 == 0:
            self.dm.player.add_hp(1)
            
        if self.dm.turn % 50 == 0:
            for m in self.monsters:
                m.add_hp(1)
            if random() < 0.5:
                self.add_monster()
        
        self.dm.turn += 1
            
    def end_security_lockdown(self):
        self.security_lockdown = False
        
    def extinguish_light_source(self, light_source):
        stack = self.dungeon_loc[light_source.row][light_source.col].item_stack
        for item in stack:
            if item == light_source:
                self.douse_squares(light_source)
                if isinstance(item, Items.LitFlare):
                    stack.remove(item)
                _msg = light_source.get_name() + ' has gone out.'
                self.dm.alert_player_to_event(light_source.row, light_source.col, self, _msg, True)

    # this could maybe be moved to GamePersistence?
    def generate_save_object(self):
        for m in self.monsters:
            m.dm = ''

        self.clear_occupants()
        _exit_point = (self.dm.player.row,self.dm.player.col)
        _save_obj = (self.map,self.dungeon_loc,self.eventQueue,self.light_sources,self.monsters, \
                self.category,self.level_num,_exit_point,self.cameras,self.upStairs,self.downStairs,\
                self.security_lockdown, self.subnet_nodes, self.cameras_active, self.security_active)

        return _save_obj
        
    # I'm going to use the Bresenham circle algorithm to generate
    # "circles" to check, and work my way out until I find a clear
    # space.  
    #
    # Sanity check: if we've searched radius > 10 and not found 
    # a clear spot, then we're probably not going to find one.
    def get_nearest_clear_space(self, r, c):
        _radius = 1
        while True:
            _pts = self.clear_bresenham_points(r, c, _radius)
            if len(_pts) > 0:
                return choice(_pts)
            _radius += 1
            if _radius > 10: return None

    def get_occupant(self, r, c):
        return self.dungeon_loc[r][c].occupant
        
    def is_clear(self,r,c):
        if not self.in_bounds(r,c):
            return False
            
        return self.map[r][c].is_passable() and self.dungeon_loc[r][c].occupant == ''

    def place_sqr(self, sqr, target_type):
        while True:
            r = randrange(1,self.lvl_length-1)
            c = randrange(1,self.lvl_width-1)
            
            if self.map[r][c].get_type() == target_type: break
        self.map[r][c] = sqr
        
    def remove_monster(self, monster, row, col):
        self.dungeon_loc[row][col].occupant = ''
        self.monsters.remove(monster)

    def resolve_events(self):
        while len(self.eventQueue) > 0 and self.eventQueue.peekAtNextPriority() <= self.dm.turn:
            event = self.eventQueue.pop()
            if event[0] == 'explosion':
                self.dm.handle_explosion(self, event[1],event[2],event[3])
                # bomb is returned, return tile to what it was
                _sqr = self.map[event[1]][event[2]]
                if isinstance(_sqr,Terrain.Trap):
                    self.map[event[1]][event[2]] = _sqr.previousTile
                    self.dm.update_sqr(self, event[1], event[2])
            elif event[0] == 'extinguish':
                self.extinguish_light_source(event[3])

    def clear_occupants(self):
        for row in self.dungeon_loc:
            for cell in row:
                cell.occupant = ''
    
    def add_feature_to_map(self, feature):
        while True:
            r = randrange(1,self.lvl_length-1)
            c = randrange(1,self.lvl_width-1)

            if self.map[r][c].get_type() == FLOOR:
                feature.row = r
                feature.col = c
                self.map[r][c] = feature
                break

    def remove_light_source(self, light_source):
        _target = ''
        for _ls in self.light_sources:
            if _ls == light_source:
                _target = _ls
                
        if _target != '':
            self.light_sources.remove(_target)

    def add_item(self, _chart):
        _item = _chart.get_item(self.level_num)
        while True:
            r = randrange(self.lvl_length)
            c = randrange(self.lvl_width)
            
            if self.map[r][c].get_type() == FLOOR:
                self.add_item_to_sqr(r,c,_item)
                break
                
    def add_pack(self, monster_name, low, high, r, c):
        for j in range(randrange(low,high+1)):
            _sqr = self.get_nearest_clear_space(r,c)
            if _sqr != None:
                _monster = MonsterFactory.get_monster_by_name(self.dm, monster_name, _sqr[0], _sqr[1])  
                self.add_monster_to_dungeon(_monster, _sqr[0], _sqr[1])
        
    def add_monster(self, monster=''):
        # This loop currently doesn't handle the oddball case where the dungeon is full!
        # Should be fixed, otherwise it will be an infinite loop, and unpleasant for the
        # player!
        
        while True: 
            try_r = randrange(0,self.lvl_length)
            try_c = randrange(0,self.lvl_width)
            _sqr = self.map[try_r][try_c]

            # This'll prevent a monster from being generated where the player will
            # appear when first entering the level
            if _sqr.get_type() in (UP_STAIRS, DOWN_STAIRS):
                continue
                
            if self.is_clear(try_r,try_c):
                r = try_r
                c = try_c
                break
            
        if monster.level < self.level_num:
            monster.level = self.level_num
        self.add_monster_to_dungeon(monster, r, c)
                
    def add_monster_to_dungeon(self, monster, r, c):
        monster.row = r
        monster.col = c
        self.dungeon_loc[r][c].occupant = monster
        self.monsters.append(monster)
        
    def get_player_start_loc(self):
        return self.player_start_loc

    def initialize_dungeon_locs(self):
        self.dungeon_loc = []
        for r in range(0,self.lvl_length):
            row = []
            for c in range(0,self.lvl_width):
                row.append(DungeonSqr(False, False, False))
            self.dungeon_loc.append(row)
            
    def begin_security_lockdown(self):
        pass