示例#1
0
 def apply_moves(self, p1_actions, p2_actions):
     new_p1_guys = [[0] * self.height for x in range(self.width)]
     new_p2_guys = [[0] * self.height for x in range(self.width)]
     for (x, y), direction in p1_actions:
         quantity = int(p1_actions[((x, y), direction)])
         if direction not in actions.ALL_ACTIONS: continue
         if self.p1_guys >= quantity:
             new_x, new_y = actions.next_pos((x, y), direction)
             if self.__is_on_board((new_x, new_y)):
                 new_p1_guys[new_x][new_y] += quantity
                 self.p1_guys[x][y] -= quantity
     for (x, y), direction in p2_actions:
         quantity = int(p2_actions[((x, y), direction)])
         if direction not in actions.ALL_ACTIONS: continue
         if self.p2_guys >= quantity:
             new_x, new_y = actions.next_pos((x, y), direction)
             if self.__is_on_board((new_x, new_y)):
                 new_p2_guys[new_x][new_y] += quantity
                 self.p2_guys[x][y] -= quantity
     for x in range(self.width):
         for y in range(self.height):
             new_p1_guys[x][y] += self.p1_guys[x][y]
             new_p2_guys[x][y] += self.p2_guys[x][y]
     self.p1_guys = new_p1_guys
     self.p2_guys = new_p2_guys
示例#2
0
 def apply_moves(self, p1_actions, p2_actions):
     new_p1_guys = [[0] * self.height for x in range(self.width)]
     new_p2_guys = [[0] * self.height for x in range(self.width)]
     for (x, y), direction in p1_actions:
         quantity = int(p1_actions[((x, y), direction)])
         if direction not in actions.ALL_ACTIONS: continue
         if len(self.p1_guys) >= quantity:
             new_x, new_y = actions.next_pos((x, y), direction)
             if self.__is_on_board((new_x, new_y)):
                 new_p1_guys[new_x][new_y] += quantity
                 self.p1_guys[x][y] -= quantity
     for (x, y), direction in p2_actions:
         quantity = int(p2_actions[((x, y), direction)])
         if direction not in actions.ALL_ACTIONS: continue
         if len(self.p2_guys) >= quantity:
             new_x, new_y = actions.next_pos((x, y), direction)
             if self.__is_on_board((new_x, new_y)):
                 new_p2_guys[new_x][new_y] += quantity
                 self.p2_guys[x][y] -= quantity
     for x in range(self.width):
         for y in range(self.height):
             new_p1_guys[x][y] += self.p1_guys[x][y]
             new_p2_guys[x][y] += self.p2_guys[x][y]
     self.p1_guys = new_p1_guys
     self.p2_guys = new_p2_guys
示例#3
0
 def get_order(self, x, y, guys, dist_to_unowned, first):
     best_action = None
     best_dist = 999
     best_food = 0.0
     for action in self.MOVE_ACTIONS:
         x2, y2 = actions.next_pos( (x,y), action)
         if not self.in_bounds(x2, y2):
             continue
         dist = dist_to_unowned[x2][y2]
         # First ignores distance, only interested in food and unowned tiles
         if first:
             if self.is_mine(x2, y2, guys):
                 dist = 999
             else:
                 dist = 0
         food = self.get_food(x2, y2)
         if dist < best_dist or (dist == best_dist and food > best_food):
             best_action = action
             best_dist = dist
             best_food = food
     
     x2, y2 = actions.next_pos( (x,y), best_action) # New pos
     if first:
         # First guy can't move if it's to a worse food spot...
         # or my guys are there already
         # or we're near the end of the game
         if self.get_food(x2, y2) <= self.get_food(x, y) \
            or self.is_mine(x2, y2, guys) \
            or self.turn_no > 500:
             return ((x, y), actions.STAY)
     
     # Make pos less attractive so others spread out (occasionally)
     if random.random() > 0.9:
         dist_to_unowned[x2][y2] += 0.1
     # Update guys
     self.update_guys(x, y, x2, y2, guys)
     # Give the order
     return ((x, y), best_action)
示例#4
0
    def get_order(self, x, y, guys, dist_to_unowned, first):
        best_action = None
        best_dist = 999
        best_food = 0.0
        for action in self.MOVE_ACTIONS:
            x2, y2 = actions.next_pos((x, y), action)
            if not self.in_bounds(x2, y2):
                continue
            dist = dist_to_unowned[x2][y2]
            # First ignores distance, only interested in food and unowned tiles
            if first:
                if self.is_mine(x2, y2, guys):
                    dist = 999
                else:
                    dist = 0
            food = self.get_food(x2, y2)
            if dist < best_dist or (dist == best_dist and food > best_food):
                best_action = action
                best_dist = dist
                best_food = food

        x2, y2 = actions.next_pos((x, y), best_action)  # New pos
        if first:
            # First guy can't move if it's to a worse food spot...
            # or my guys are there already
            # or we're near the end of the game
            if self.get_food(x2, y2) <= self.get_food(x, y) \
               or self.is_mine(x2, y2, guys) \
               or self.turn_no > 500:
                return ((x, y), actions.STAY)

        # Make pos less attractive so others spread out (occasionally)
        if random.random() > 0.9:
            dist_to_unowned[x2][y2] += 0.1
        # Update guys
        self.update_guys(x, y, x2, y2, guys)
        # Give the order
        return ((x, y), best_action)
示例#5
0
 def take_turn(self, guys, my_food, their_food, my_money, their_money):
     # Update turn number
     self.turn_no += 1
     
     # Update unoccupied_time: bias movement toward open spaces
     for x in range(self.width):
         for y in range(self.height):
             if guys[x][y]:
                 self.unoccupied_time[x][y] = 0
             else:
                 self.unoccupied_time[x][y] += 1
                 
     
     # Make a grid of distance to closest non-owned tile
     # This got twisted into becoming a general attractiveness measure
     dist_to_unowned = [ [999] * self.height for i in range(self.width) ]
     open = [] # open list of seeds to grow a distance/attractiveness grid
     for x in range(self.width):
         for y in range(self.height):
             # Longer unowned and higher food tiles are more attractive.
             # Magic numbers seemed to help so it wouldn't be overwhelmed by
             # attraction to unoccupied area
             attractiveness = self.unoccupied_time[x][y] * (1 + self.get_food(x,y)) * 0.1
             # Only add non-owned tiles
             if not self.is_mine(x, y, guys):
                 # Attraction is represented as negative distance
                 open.append( (-attractiveness, x, y) )
     
     for d, x, y in open:
         dist_to_unowned[x][y] = d
     # Djikstra's algorithm to fill out grid of shortest distances
     heapq.heapify(open)
     while len(open) > 0:
         d, x, y = heapq.heappop(open)
         if dist_to_unowned[x][y] < d:
             continue # Shorter dist found already
         for m in self.MOVE_ACTIONS:
             x2, y2 = actions.next_pos( (x,y), m)
             if not self.in_bounds(x2, y2):
                 continue
             # Bias around enemy guys
             # and places there are lots of my guys already
             cost = 1
             if guys[x2][y2]:
                 num_guys, is_mine = guys[x2][y2]
                 if is_mine:
                     cost = 1 + 0.1*num_guys
                 else:
                     cost = num_guys
             if dist_to_unowned[x2][y2] > d + cost:
                 dist_to_unowned[x2][y2] = d + cost
                 heapq.heappush(open, (d + cost, x2, y2))
     
     # Make a list of all my guys, sorted by most to least food
     # Sorting was originally to help guys move toward higher food but I
     # don't think it's actually necessary any more.
     all_guys = []
     for x in range(self.width):
         for y in range(self.height):
             if not self.is_mine(x, y, guys): continue
             num_guys, is_mine = guys[x][y]
             all_guys.append( (self.get_food(x,y), x, y, num_guys) )
     all_guys.sort(reverse=True)
     
     # Get the best order for each guy. Record where guys still can move
     # (max of 1 guy still can move in each square as only the first guy
     # might choose to STAY)
     orders = {}
     still_can_move = {}
     for unused, x, y, num_guys in all_guys:
         for i in range(num_guys):
             # Get the best order for this guy
             position, action = self.get_order(x, y, guys, dist_to_unowned, i == 0)
             
             if action == actions.STAY:
                 still_can_move[position] = True
             else:
                 order = (position, action)
                 if order not in orders:
                     orders[order] = 1
                 else:
                     orders[order] += 1
     # Try moving the guys that still_can_move if other guys have moved into their square
     # Iterate over orders looking to see if destination square still can move
     open = orders.keys()
     while len(open) > 0:
         # Order stores origin position, translate to destination position
         origin, action = open.pop()
         position = actions.next_pos(origin, action)
         if position in still_can_move:
             still_can_move.pop(position)
             x, y = position
             position, action = self.get_order(x, y, guys, dist_to_unowned, False)
             # Action can never be STAY because this is not being treated as the first guy
             # on the square any more (because someone else is taking its space as first)
             order = (position, action)
             if order not in orders:
                 orders[order] = 1
             else:
                 orders[order] += 1
             open.append(order)
     
     return orders
示例#6
0
    def take_turn(self, guys, my_food, their_food, my_money, their_money):
        width = len(guys)
        height = len(guys[0])
        MOVE_ACTIONS = actions.ALL_ACTIONS[1:]
        
        ### update self.unoccupied_time: bias movement toward open spaces
        for x in range(width):
            for y in range(height):
                if guys[x][y]:
                    self.unoccupied_time[x][y] = 0
                else:
                    self.unoccupied_time[x][y] += 1
                    
        
        ### Make a "map" of distance to closest non-owned square
        dist_to_unowned = [ [999] * height for i in range(width) ]
        open = [] # open list
        for x in range(width):
            for y in range(height):
                food = 1.0 - self.money_payout_rates[x][y]
                attractiveness = self.unoccupied_time[x][y] * (1 + food)
                if not guys[x][y]:
                    open.append( (-attractiveness,x,y) )
                else:
                    num_guys, is_mine = guys[x][y]
                    if not is_mine:
                        open.append( (-attractiveness,x,y) )
        
        for d, x, y in open:
            dist_to_unowned[x][y] = d
        # Djikstra to fill out map
        heapq.heapify(open)
        while len(open) > 0:
            d, x, y = heapq.heappop(open)
            if dist_to_unowned[x][y] < d:
                continue # Better dist found already
            for m in MOVE_ACTIONS:
                x2, y2 = actions.next_pos( (x,y), m)
                if not self.in_bounds(x2, y2):
                    continue
                # Bias around enemy guys
                # and places there are lots of my guys already
                cost = 1
                if guys[x2][y2]:
                    num_guys, is_mine = guys[x2][y2]
                    if is_mine:
                        cost = 1 + 0.1*num_guys
                    else:
                        cost = num_guys
                if dist_to_unowned[x2][y2] > d + cost:
                    dist_to_unowned[x2][y2] = d + cost
                    heapq.heappush(open, (d + cost, x2, y2))
        # for y in range(height):
            # for x in range(width):
                # print dist_to_unowned[x][y],
            # print ''
        
        

        orders = {}
        for x in range(width):
            for y in range(height):
                if not guys[x][y]: continue

                num_guys, is_mine = guys[x][y]
                if not is_mine: continue

                # Move all but 1 guys
                for i in range(num_guys-1):
                    action = None
                    best_dist = 999
                    best_food = 0.0
                    for m in MOVE_ACTIONS:
                        x2, y2 = actions.next_pos( (x,y), m)
                        if not self.in_bounds(x2, y2):
                            continue
                        dist = dist_to_unowned[x2][y2]
                        food = 1.0 - self.money_payout_rates[x2][y2]
                        if dist < best_dist or (dist == best_dist and food > best_food):
                            action = m
                            best_dist = dist
                            best_food = food
                    # Make pos less attractive so others spread out (occasionally)
                    if random.random() > 0.9:
                        x2, y2 = actions.next_pos( (x,y), action)
                        dist_to_unowned[x2][y2] += 0.1
                    
                    # Give the order
                    key = ((x, y), action)
                    if key not in orders:
                        orders[key] = 1
                    else:
                        orders[key] += 1
        return orders
示例#7
0
    def take_turn(self, guys, my_food, their_food, my_money, their_money):
        self.turn_no += 1
        width = len(guys)
        height = len(guys[0])
        MOVE_ACTIONS = actions.ALL_ACTIONS[1:]
        
        ### update self.unoccupied_time: bias movement toward open spaces
        for x in range(width):
            for y in range(height):
                if guys[x][y]:
                    self.unoccupied_time[x][y] = 0
                else:
                    self.unoccupied_time[x][y] += 1
                    
        
        ### Make a "map" of distance to closest non-owned square
        dist_to_unowned = [ [999] * height for i in range(width) ]
        open = [] # open list
        for x in range(width):
            for y in range(height):
                attractiveness = self.unoccupied_time[x][y] * (1 + self.get_food(x,y)) * 0.1
                if not guys[x][y]:
                    open.append( (-attractiveness,x,y) )
                else:
                    num_guys, is_mine = guys[x][y]
                    if not is_mine:
                        open.append( (-attractiveness,x,y) )
        
        for d, x, y in open:
            dist_to_unowned[x][y] = d
        # Djikstra to fill out map
        heapq.heapify(open)
        while len(open) > 0:
            d, x, y = heapq.heappop(open)
            if dist_to_unowned[x][y] < d:
                continue # Better dist found already
            for m in MOVE_ACTIONS:
                x2, y2 = actions.next_pos( (x,y), m)
                if not self.in_bounds(x2, y2):
                    continue
                # Bias around enemy guys
                # and places there are lots of my guys already
                cost = 1
                if guys[x2][y2]:
                    num_guys, is_mine = guys[x2][y2]
                    if is_mine:
                        cost = 1 + 0.1*num_guys
                    else:
                        cost = num_guys
                if dist_to_unowned[x2][y2] > d + cost:
                    dist_to_unowned[x2][y2] = d + cost
                    heapq.heappush(open, (d + cost, x2, y2))
        # for y in range(height):
            # for x in range(width):
                # print dist_to_unowned[x][y],
            # print ''
        
        

        orders = {}
        all_guys = [] # in order of best food, most food at start
        for x in range(width):
            for y in range(height):
                if not guys[x][y]: continue

                num_guys, is_mine = guys[x][y]
                if not is_mine: continue
                
                all_guys.append( (self.get_food(x,y), x, y, num_guys) )
        all_guys.sort(reverse=True)
        
        for food, x, y, num_guys in all_guys:
            # Move guys
            for i in range(num_guys):
                action = None
                best_dist = 999
                best_food = 0.0
                for m in MOVE_ACTIONS:
                    x2, y2 = actions.next_pos( (x,y), m)
                    if not self.in_bounds(x2, y2):
                        continue
                    dist = dist_to_unowned[x2][y2]
                    if i == 0: # First guy ignores distance, only interested in food and unowned tiles
                        if self.is_mine(x2, y2, guys):
                            dist = 999
                        else:
                            dist = 0
                    food = self.get_food(x2,y2)
                    if dist < best_dist or (dist == best_dist and food > best_food):
                        action = m
                        best_dist = dist
                        best_food = food
                
                x2, y2 = actions.next_pos( (x,y), action) # New pos
                if i == 0:
                    # First guy can only move if it's to a better food spot...
                    if self.get_food(x2,y2) <= self.get_food(x,y):
                        continue
                    # and my guys aren't there already
                    if self.is_mine(x2,y2,guys):
                        continue
                    # and we're not near the end of the game
                    if self.turn_no > 750:
                        continue
                # Make pos less attractive so others spread out (occasionally)
                if random.random() > 0.9:
                    dist_to_unowned[x2][y2] += 0.1
                
                # Give the order
                key = ((x, y), action)
                if key not in orders:
                    orders[key] = 1
                else:
                    orders[key] += 1
                # Update guys
                self.update_guys(x,y,x2,y2,guys)
                        
        return orders
示例#8
0
    def apply_actions(self, p1_actions, p2_actions, turn):
        new_p1_guys = [[0] * self.height for x in range(self.width)]
        new_p2_guys = [[0] * self.height for x in range(self.width)]
        # Resolve P1 actions
        orders, guys_to_hire = p1_actions
        for (x, y), action in orders:
            quantity = int(orders[((x, y), action)])
            if action not in actions.ALL_ACTIONS:
                continue
            if self.p1_guys[x][y] >= quantity:
                if action in actions.MOVE_ACTIONS:
                    # Resolve movement
                    new_x, new_y = actions.next_pos((x, y), action)
                    if self.__is_on_board((new_x, new_y)):
                        new_p1_guys[new_x][new_y] += quantity
                        self.p1_guys[x][y] -= quantity
                elif action == actions.PLANT:
                    # Plant a plant if there's no plant already here and they
                    # have enough seeds.
                    if self.p1_plants[x][y] < 0 and self.p2_plants[x][
                            y] < 0 and self.p1_seeds > 0:
                        self.p1_plants[x][y] = turn
                        self.p1_seeds = self.p1_seeds - 1
                elif action == actions.HARVEST:
                    # Harvest a plant, but not one you planted this turn!
                    if self.p1_plants[x][y] >= 0 and self.p1_plants[x][
                            y] != turn:
                        gold, seeds = actions.get_plant_payout(
                            turn - self.p1_plants[x][y], True)
                        self.p1_gold = self.p1_gold + gold
                        self.p1_seeds = self.p1_seeds + seeds
                        self.p1_plants[x][y] = None
                    elif self.p2_plants[x][y] >= 0 and self.p2_plants[x][
                            y] != turn:
                        gold, seeds = actions.get_plant_payout(
                            turn - self.p2_plants[x][y], False)
                        self.p1_gold = self.p1_gold + gold
                        self.p1_seeds = self.p1_seeds + seeds
                        self.p2_plants[x][y] = None
        # Hire more guys for P1
        if self.p1_gold >= (guys_to_hire * actions.GOLD_PER_GUY):
            self.p1_guys_to_spawn = guys_to_hire
            self.p1_gold = self.p1_gold - (guys_to_hire * actions.GOLD_PER_GUY)

        # Resolve P2 actions
        orders, guys_to_hire = p2_actions
        for (x, y), action in orders:
            quantity = int(orders[((x, y), action)])
            if action not in actions.ALL_ACTIONS: continue
            if self.p2_guys[x][y] >= quantity:
                if action in actions.MOVE_ACTIONS:
                    # Resolve movement
                    new_x, new_y = actions.next_pos((x, y), action)
                    if self.__is_on_board((new_x, new_y)):
                        new_p2_guys[new_x][new_y] += quantity
                        self.p2_guys[x][y] -= quantity
                elif action == actions.PLANT:
                    # Plant a plant if there's no plant already here and they
                    # have enough seeds.
                    if self.p2_plants[x][y] < 0 and self.p1_plants[x][
                            y] < 0 and self.p2_seeds > 0:
                        self.p2_plants[x][y] = turn
                        self.p2_seeds = self.p2_seeds - 1
                elif action == actions.HARVEST:
                    # Harvest a plant
                    if self.p2_plants[x][y] >= 0 and self.p2_plants[x][
                            y] != turn:
                        gold, seeds = actions.get_plant_payout(
                            turn - self.p2_plants[x][y], True)
                        self.p2_gold = self.p2_gold + gold
                        self.p2_seeds = self.p2_seeds + seeds
                        self.p2_plants[x][y] = None
                    elif self.p1_plants[x][y] >= 0 and self.p1_plants[x][
                            y] != turn:
                        gold, seeds = actions.get_plant_payout(
                            turn - self.p1_plants[x][y], False)
                        self.p2_gold = self.p2_gold + gold
                        self.p2_seeds = self.p2_seeds + seeds
                        self.p1_plants[x][y] = None
        # Hire more guys for P2
        if self.p2_gold >= (guys_to_hire * actions.GOLD_PER_GUY):
            self.p2_guys_to_spawn = guys_to_hire
            self.p2_gold = self.p2_gold - (guys_to_hire * actions.GOLD_PER_GUY)

        for x in range(self.width):
            for y in range(self.height):
                new_p1_guys[x][y] += self.p1_guys[x][y]
                new_p2_guys[x][y] += self.p2_guys[x][y]
        self.p1_guys = new_p1_guys
        self.p2_guys = new_p2_guys

        # Keep track of the max gold and max seeds seen so far.  We'll
        # use this to normalize the values for the line graph in the
        # visualization.
        self.max_gold = max(self.max_gold, self.p1_gold, self.p2_gold)
        self.max_seeds = max(self.max_seeds, self.p1_seeds, self.p2_seeds)
示例#9
0
    def take_turn(self, guys, my_food, their_food, my_money, their_money):
        # Update turn number
        self.turn_no += 1

        # Update unoccupied_time: bias movement toward open spaces
        for x in range(self.width):
            for y in range(self.height):
                if guys[x][y]:
                    self.unoccupied_time[x][y] = 0
                else:
                    self.unoccupied_time[x][y] += 1

        # Make a grid of distance to closest non-owned tile
        # This got twisted into becoming a general attractiveness measure
        dist_to_unowned = [[999] * self.height for i in range(self.width)]
        open = []  # open list of seeds to grow a distance/attractiveness grid
        for x in range(self.width):
            for y in range(self.height):
                # Longer unowned and higher food tiles are more attractive.
                # Magic numbers seemed to help so it wouldn't be overwhelmed by
                # attraction to unoccupied area
                attractiveness = self.unoccupied_time[x][y] * (
                    1 + self.get_food(x, y)) * 0.1
                # Only add non-owned tiles
                if not self.is_mine(x, y, guys):
                    # Attraction is represented as negative distance
                    open.append((-attractiveness, x, y))

        for d, x, y in open:
            dist_to_unowned[x][y] = d
        # Djikstra's algorithm to fill out grid of shortest distances
        heapq.heapify(open)
        while len(open) > 0:
            d, x, y = heapq.heappop(open)
            if dist_to_unowned[x][y] < d:
                continue  # Shorter dist found already
            for m in self.MOVE_ACTIONS:
                x2, y2 = actions.next_pos((x, y), m)
                if not self.in_bounds(x2, y2):
                    continue
                # Bias around enemy guys
                # and places there are lots of my guys already
                cost = 1
                if guys[x2][y2]:
                    num_guys, is_mine = guys[x2][y2]
                    if is_mine:
                        cost = 1 + 0.1 * num_guys
                    else:
                        cost = num_guys
                if dist_to_unowned[x2][y2] > d + cost:
                    dist_to_unowned[x2][y2] = d + cost
                    heapq.heappush(open, (d + cost, x2, y2))

        # Make a list of all my guys, sorted by most to least food
        # Sorting was originally to help guys move toward higher food but I
        # don't think it's actually necessary any more.
        all_guys = []
        for x in range(self.width):
            for y in range(self.height):
                if not self.is_mine(x, y, guys): continue
                num_guys, is_mine = guys[x][y]
                all_guys.append((self.get_food(x, y), x, y, num_guys))
        all_guys.sort(reverse=True)

        # Get the best order for each guy. Record where guys still can move
        # (max of 1 guy still can move in each square as only the first guy
        # might choose to STAY)
        orders = {}
        still_can_move = {}
        for unused, x, y, num_guys in all_guys:
            for i in range(num_guys):
                # Get the best order for this guy
                position, action = self.get_order(x, y, guys, dist_to_unowned,
                                                  i == 0)

                if action == actions.STAY:
                    still_can_move[position] = True
                else:
                    order = (position, action)
                    if order not in orders:
                        orders[order] = 1
                    else:
                        orders[order] += 1
        # Try moving the guys that still_can_move if other guys have moved into their square
        # Iterate over orders looking to see if destination square still can move
        open = orders.keys()
        while len(open) > 0:
            # Order stores origin position, translate to destination position
            origin, action = open.pop()
            position = actions.next_pos(origin, action)
            if position in still_can_move:
                still_can_move.pop(position)
                x, y = position
                position, action = self.get_order(x, y, guys, dist_to_unowned,
                                                  False)
                # Action can never be STAY because this is not being treated as the first guy
                # on the square any more (because someone else is taking its space as first)
                order = (position, action)
                if order not in orders:
                    orders[order] = 1
                else:
                    orders[order] += 1
                open.append(order)

        return orders
示例#10
0
    def apply_actions(self, p1_actions, p2_actions, turn):
        new_p1_guys = [[0] * self.height for x in range(self.width)]
        new_p2_guys = [[0] * self.height for x in range(self.width)]
        # Resolve P1 actions
        orders, guys_to_hire = p1_actions
        for (x, y), action in orders:
            quantity = int(orders[((x, y), action)])
            if action not in actions.ALL_ACTIONS:
                continue
            if self.p1_guys[x][y] >= quantity:
                if action in actions.MOVE_ACTIONS:
                    # Resolve movement
                    new_x, new_y = actions.next_pos((x, y), action)
                    if self.__is_on_board((new_x, new_y)):
                        new_p1_guys[new_x][new_y] += quantity
                        self.p1_guys[x][y] -= quantity
                elif action == actions.PLANT:
                    # Plant a plant if there's no plant already here and they
                    # have enough seeds.
                    if self.p1_plants[x][y] < 0 and self.p2_plants[x][y] < 0 and self.p1_seeds > 0:
                        self.p1_plants[x][y] = turn
                        self.p1_seeds = self.p1_seeds - 1
                elif action == actions.HARVEST:
                    # Harvest a plant, but not one you planted this turn!
                    if self.p1_plants[x][y] >= 0 and self.p1_plants[x][y] != turn:
                        gold, seeds = actions.get_plant_payout(turn - self.p1_plants[x][y], True)
                        self.p1_gold = self.p1_gold + gold
                        self.p1_seeds = self.p1_seeds + seeds
                        self.p1_plants[x][y] = None                        
                    elif self.p2_plants[x][y] >= 0 and self.p2_plants[x][y] != turn:
                        gold, seeds = actions.get_plant_payout(turn - self.p2_plants[x][y], False)
                        self.p1_gold = self.p1_gold + gold
                        self.p1_seeds = self.p1_seeds + seeds
                        self.p2_plants[x][y] = None      
        # Hire more guys for P1
        if self.p1_gold >= (guys_to_hire * actions.GOLD_PER_GUY):
            self.p1_guys_to_spawn = guys_to_hire
            self.p1_gold = self.p1_gold - (guys_to_hire * actions.GOLD_PER_GUY) 
        
        # Resolve P2 actions
        orders, guys_to_hire = p2_actions
        for (x, y), action in orders:
            quantity = int(orders[((x, y), action)])
            if action not in actions.ALL_ACTIONS: continue
            if self.p2_guys[x][y] >= quantity:
                if action in actions.MOVE_ACTIONS:
                    # Resolve movement
                    new_x, new_y = actions.next_pos((x, y), action)
                    if self.__is_on_board((new_x, new_y)):
                        new_p2_guys[new_x][new_y] += quantity
                        self.p2_guys[x][y] -= quantity
                elif action == actions.PLANT:
                    # Plant a plant if there's no plant already here and they
                    # have enough seeds.
                    if self.p2_plants[x][y] < 0 and self.p1_plants[x][y] < 0 and self.p2_seeds > 0:
                        self.p2_plants[x][y] = turn
                        self.p2_seeds = self.p2_seeds - 1
                elif action == actions.HARVEST:
                    # Harvest a plant
                    if self.p2_plants[x][y] >= 0 and self.p2_plants[x][y] != turn:
                        gold, seeds = actions.get_plant_payout(turn - self.p2_plants[x][y], True)
                        self.p2_gold = self.p2_gold + gold
                        self.p2_seeds = self.p2_seeds + seeds
                        self.p2_plants[x][y] = None                        
                    elif self.p1_plants[x][y] >= 0 and self.p1_plants[x][y] != turn:
                        gold, seeds = actions.get_plant_payout(turn - self.p1_plants[x][y], False)
                        self.p2_gold = self.p2_gold + gold
                        self.p2_seeds = self.p2_seeds + seeds
                        self.p1_plants[x][y] = None                     
        # Hire more guys for P2
        if self.p2_gold >= (guys_to_hire * actions.GOLD_PER_GUY):
            self.p2_guys_to_spawn = guys_to_hire
            self.p2_gold = self.p2_gold - (guys_to_hire * actions.GOLD_PER_GUY)

        for x in range(self.width):
            for y in range(self.height):
                new_p1_guys[x][y] += self.p1_guys[x][y]
                new_p2_guys[x][y] += self.p2_guys[x][y]
        self.p1_guys = new_p1_guys
        self.p2_guys = new_p2_guys
        
        # Keep track of the max gold and max seeds seen so far.  We'll
        # use this to normalize the values for the line graph in the
        # visualization.
        self.max_gold = max(self.max_gold, self.p1_gold, self.p2_gold)
        self.max_seeds = max(self.max_seeds, self.p1_seeds, self.p2_seeds)
示例#11
0
    def take_turn(self, guys, my_food, their_food, my_money, their_money):
        width = len(guys)
        height = len(guys[0])
        MOVE_ACTIONS = actions.ALL_ACTIONS[1:]

        ### update self.unoccupied_time: bias movement toward open spaces
        for x in range(width):
            for y in range(height):
                if guys[x][y]:
                    self.unoccupied_time[x][y] = 0
                else:
                    self.unoccupied_time[x][y] += 1

        ### Make a "map" of distance to closest non-owned square
        dist_to_unowned = [[999] * height for i in range(width)]
        open = []  # open list
        for x in range(width):
            for y in range(height):
                food = 1.0 - self.money_payout_rates[x][y]
                attractiveness = self.unoccupied_time[x][y] * (1 + food)
                if not guys[x][y]:
                    open.append((-attractiveness, x, y))
                else:
                    num_guys, is_mine = guys[x][y]
                    if not is_mine:
                        open.append((-attractiveness, x, y))

        for d, x, y in open:
            dist_to_unowned[x][y] = d
        # Djikstra to fill out map
        heapq.heapify(open)
        while len(open) > 0:
            d, x, y = heapq.heappop(open)
            if dist_to_unowned[x][y] < d:
                continue  # Better dist found already
            for m in MOVE_ACTIONS:
                x2, y2 = actions.next_pos((x, y), m)
                if not self.in_bounds(x2, y2):
                    continue
                # Bias around enemy guys
                # and places there are lots of my guys already
                cost = 1
                if guys[x2][y2]:
                    num_guys, is_mine = guys[x2][y2]
                    if is_mine:
                        cost = 1 + 0.1 * num_guys
                    else:
                        cost = num_guys
                if dist_to_unowned[x2][y2] > d + cost:
                    dist_to_unowned[x2][y2] = d + cost
                    heapq.heappush(open, (d + cost, x2, y2))
        # for y in range(height):
        # for x in range(width):
        # print dist_to_unowned[x][y],
        # print ''

        orders = {}
        for x in range(width):
            for y in range(height):
                if not guys[x][y]: continue

                num_guys, is_mine = guys[x][y]
                if not is_mine: continue

                # Move all but 1 guys
                for i in range(num_guys - 1):
                    action = None
                    best_dist = 999
                    best_food = 0.0
                    for m in MOVE_ACTIONS:
                        x2, y2 = actions.next_pos((x, y), m)
                        if not self.in_bounds(x2, y2):
                            continue
                        dist = dist_to_unowned[x2][y2]
                        food = 1.0 - self.money_payout_rates[x2][y2]
                        if dist < best_dist or (dist == best_dist
                                                and food > best_food):
                            action = m
                            best_dist = dist
                            best_food = food
                    # Make pos less attractive so others spread out (occasionally)
                    if random.random() > 0.9:
                        x2, y2 = actions.next_pos((x, y), action)
                        dist_to_unowned[x2][y2] += 0.1

                    # Give the order
                    key = ((x, y), action)
                    if key not in orders:
                        orders[key] = 1
                    else:
                        orders[key] += 1
        return orders