Example #1
0
    def handle_mouseup(self, event, drag=False):
        # It's simply a timing error
        if self.screen.selected_actors == []:
            return

        relative_pos = (event.pos[0] - self.position.left,
                        event.pos[1] - self.position.top)

        col = math.floor(relative_pos[0] / self.grid_size[0])
        row = math.floor(relative_pos[1] / self.grid_size[1])
        col_count = int(math.floor(self.size[0] / self.grid_size[0]))

        index = int((col_count * row) + col)

        # No button there? Ignore the click but they clicked the menu
        # so we don't want to pass this back to the screen
        if index >= len(self.buttons):
            return True

        # Get the information for the button
        item_name, item_image, queue_length = self.buttons[index]

        # What are we looking at?
        if item_name in self.screen.actor_types:
            actor_type = self.screen.actor_types[item_name]

            if "placement_image" in actor_type:
                # It has a placement image, it's placed by the player
                self.screen.place_actor_mode(item_name)

            else:
                # No placement image, the actor is added to the build queue
                # and placed later
                # TODO: Make this game-specific rule go in a game-specific file
                # When starting Downstream this errored
                choice = (None, 999999)
                for a in self.screen.selected_actors:
                    if actor_lib.can_build(
                            self.screen.actor_types[a.actor_type], actor_type,
                            self.screen.build_lists):
                        if len(a.build_queue) < choice[1]:
                            choice = (a, len(a.build_queue))

                if choice[0] != None:
                    choice[0].build_queue.append(item_name)
                    self.update_queue_sizes()
                else:
                    raise Exception(
                        """Cannot build that unit using current selection:
item_name = %s
Selection: %s""" % (item_name,
                    [a.actor_type for a in self.screen.selected_actors]))

        else:
            raise Exception("Not found in actor types")

        return True
Example #2
0
    def handle_mouseup(self, event, drag=False):
        # It's simply a timing error
        if self.screen.selected_actors == []:
            return
        
        relative_pos = (event.pos[0] - self.position.left, event.pos[1] - self.position.top)
        
        col = math.floor(relative_pos[0]/self.grid_size[0])
        row = math.floor(relative_pos[1]/self.grid_size[1])
        col_count = int(math.floor(self.size[0]/self.grid_size[0]))
        
        index = int((col_count * row) + col)
        
        # No button there? Ignore the click but they clicked the menu
        # so we don't want to pass this back to the screen
        if index >= len(self.buttons):
            return True
        
        # Get the information for the button
        item_name, item_image, queue_length = self.buttons[index]
        
        # What are we looking at?
        if item_name in self.screen.actor_types:
            actor_type = self.screen.actor_types[item_name]
            
            if "placement_image" in actor_type:
                # It has a placement image, it's placed by the player
                self.screen.place_actor_mode(item_name)
                
            else:
                # No placement image, the actor is added to the build queue
                # and placed later
                # TODO: Make this game-specific rule go in a game-specific file
                # When starting Downstream this errored
                choice = (None, 999999)
                for a in self.screen.selected_actors:
                    if actor_lib.can_build(self.screen.actor_types[a.actor_type], actor_type, self.screen.build_lists):
                        if len(a.build_queue) < choice[1]:
                            choice = (a, len(a.build_queue))
                
                if choice[0] != None:
                    choice[0].build_queue.append(item_name)
                    self.update_queue_sizes()
                else:
                    raise Exception("""Cannot build that unit using current selection:
item_name = %s
Selection: %s""" % (item_name, [a.actor_type for a in self.screen.selected_actors]))
                
                    
        else:
            raise Exception("Not found in actor types")
        
        return True
Example #3
0
    def construct_attack(self, base_name):
        the_base = self.bases[base_name]
        attacker_list = the_base['attacks'][the_base['current_attack']]

        missing = {}
        found = []
        for a in attacker_list:
            if a not in missing:
                missing[a] = 0
            missing[a] += 1

        # Find out what we've got in the base that fits into
        # the list of units we plan to attack with
        for a in the_base['current_buildings']:
            the_actor = self.own_actors[a]

            if the_actor.actor_type in missing:
                if missing[the_actor.actor_type] > 0:
                    missing[the_actor.actor_type] -= 1
                    found.append(a)

        # We now have a list of what we're missing
        total_missing = sum([v for k, v in missing.items()])

        if total_missing == 0:
            # Do stuff
            self.commence_attack(base_name, found)

        else:
            builders = {}

            for a_type, amount in missing.items():

                if a_type not in builders:
                    builders[a_type] = []
                    for b in the_base['current_buildings']:
                        the_builder = self.own_actors[b].actor_type
                        if actor_lib.can_build(
                                builder_type=self.actor_types[the_builder],
                                item_type=self.actor_types[a_type],
                                build_lists=self.build_lists,
                        ):
                            builders[a_type].append(b)

                    # Now we find out if any of them have a slot in their queue free
                    for b in builders[a_type]:
                        the_builder = self.own_actors[b]
                        if the_builder.build_queue == []:
                            self.issue_orders(b,
                                              "build",
                                              pos=None,
                                              target=a_type)
Example #4
0
 def construct_attack(self, base_name):
     the_base = self.bases[base_name]
     attacker_list = the_base['attacks'][the_base['current_attack']]
     
     missing = {}
     found = []
     for a in attacker_list:
         if a not in missing:
             missing[a] = 0
         missing[a] += 1
     
     # Find out what we've got in the base that fits into
     # the list of units we plan to attack with
     for a in the_base['current_buildings']:
         the_actor = self.own_actors[a]
         
         if the_actor.actor_type in missing:
             if missing[the_actor.actor_type] > 0:
                 missing[the_actor.actor_type] -= 1
                 found.append(a)
     
     # We now have a list of what we're missing
     total_missing = sum([v for k,v in missing.items()])
     
     if total_missing == 0:
         # Do stuff
         self.commence_attack(base_name, found)
     
     else:
         builders = {}
         
         for a_type, amount in missing.items():
             
             if a_type not in builders:
                 builders[a_type] = []
                 for b in the_base['current_buildings']:
                     the_builder = self.own_actors[b].actor_type
                     if actor_lib.can_build(
                         builder_type = self.actor_types[the_builder],
                         item_type = self.actor_types[a_type],
                         build_lists = self.build_lists,
                     ):
                         builders[a_type].append(b)
                 
                 # Now we find out if any of them have a slot in their queue free
                 for b in builders[a_type]:
                     the_builder = self.own_actors[b]
                     if the_builder.build_queue == []:
                         self.issue_orders(b, "build", pos=None, target=a_type)
Example #5
0
 def plan_attacks(self):
     for base_name, base_data in self.bases.items():
         
         # Has it already selected an attack?
         if base_data['current_attack'] != None:
             # TODO check to see if attack has been constructed
             self.construct_attack(base_name)
             continue
         
         # Find out which of the attacks it can make
         buildable_attacks = set()
         buildable_units = set()
         unbuildable_units = set()
         for attack_id, attacker_list in base_data['attacks'].items():
             cannot_build_attack = False
             
             for a in attacker_list:
                 if a in buildable_units:
                     continue
                 if a in unbuildable_units:
                     cannot_build_attack = True
                     continue
                 
                 is_buildable = False
                 for b in base_data['current_buildings']:
                     the_builder = self.own_actors[b].actor_type
                     if actor_lib.can_build(
                         builder_type = self.actor_types[the_builder],
                         item_type = self.actor_types[a],
                         build_lists = self.build_lists,
                     ):
                         is_buildable = True
                 
                 if is_buildable:
                     buildable_units.add(a)
                 else:
                     unbuildable_units.add(a)
                     cannot_build_attack = True
             
             if cannot_build_attack == True:
                 continue
             
             buildable_attacks.add(attack_id)
         
         # Pick an attack to build, it'll get sorted in the next logic cycle
         if len(buildable_attacks) > 0:
             a = random.choice(list(buildable_attacks))
             base_data['current_attack'] = a
Example #6
0
    def plan_attacks(self):
        for base_name, base_data in self.bases.items():

            # Has it already selected an attack?
            if base_data['current_attack'] != None:
                # TODO check to see if attack has been constructed
                self.construct_attack(base_name)
                continue

            # Find out which of the attacks it can make
            buildable_attacks = set()
            buildable_units = set()
            unbuildable_units = set()
            for attack_id, attacker_list in base_data['attacks'].items():
                cannot_build_attack = False

                for a in attacker_list:
                    if a in buildable_units:
                        continue
                    if a in unbuildable_units:
                        cannot_build_attack = True
                        continue

                    is_buildable = False
                    for b in base_data['current_buildings']:
                        the_builder = self.own_actors[b].actor_type
                        if actor_lib.can_build(
                                builder_type=self.actor_types[the_builder],
                                item_type=self.actor_types[a],
                                build_lists=self.build_lists,
                        ):
                            is_buildable = True

                    if is_buildable:
                        buildable_units.add(a)
                    else:
                        unbuildable_units.add(a)
                        cannot_build_attack = True

                if cannot_build_attack == True:
                    continue

                buildable_attacks.add(attack_id)

            # Pick an attack to build, it'll get sorted in the next logic cycle
            if len(buildable_attacks) > 0:
                a = random.choice(list(buildable_attacks))
                base_data['current_attack'] = a
Example #7
0
 def place_actor_from_click(self, event, drag, actor_data):
     self.place_image = None
     actor_data['pos'] = [event.pos[0] - self.draw_margin[0], event.pos[1] - self.draw_margin[1], 0]
     actor_data['team'] = self.player_team
     
     # If holding the shift key, allow them to continue placing
     mods = pygame.key.get_mods()
     if KMOD_SHIFT & mods:
         self.place_actor_mode(actor_data['type'])
     
     builders = []
     for a in self.selected_actors:
         if actor_lib.can_build(self.actor_types[a.actor_type], self.actor_types[actor_data['type']], self.build_lists):
             builders.append(a)
     
     return self.place_actor(actor_data, builders=builders)
Example #8
0
 def inspect_bases(self):
     # First find out which buildings we are missing
     for base_name, base_data in self.bases.items():
         base_area = (
             base_data['location'][0] - base_data['size'][0],
             base_data['location'][1] - base_data['size'][1],
             
             base_data['location'][0] + base_data['size'][0],
             base_data['location'][1] + base_data['size'][1],
         )
         
         buildings_needed = set(base_data['buildings'])
         
         # Reset this now
         base_data['current_buildings'] = []
         
         # Get all buildings within this base
         found_buildings = {}
         total_needed = {}
         for b in buildings_needed:
             found_buildings[b] = 0
             total_needed[b] = 0
         
         for b in base_data['buildings']:
             total_needed[b] += 1
         
         # Loop through all actors and see what we've got
         for i, a in self.own_actors.items():
             if actor_lib.is_inside(a, base_area):
                 if a.actor_type in buildings_needed:
                     found_buildings[a.actor_type] += 1
                     
                     if a.completion >= 100:
                         base_data['current_buildings'].append(a.oid)
         
         # Now also loop through all the buildings_in_progress
         # Use a range loop so we can update the list as we go
         for i in range(len(base_data['buildings_in_progress'])-1, -1, -1):
             b, ttl = base_data['buildings_in_progress'][i]
             
             if ttl <= 0:
                 del(base_data['buildings_in_progress'][i])
                 continue
             
             base_data['buildings_in_progress'][i][1] -= 1
             
             if b in found_buildings:
                 found_buildings[b] += 1
         
         # Now find out what we are missing
         missing = {}
         for b in buildings_needed:
             m = total_needed[b] - found_buildings[b]
             if m > 0:
                 missing[b] = m
         
         # None missing? We can stop looking around now
         if missing == {}:
             continue
         
         # Now find out which builders we can use
         # Narrow down our list of builders so we don't later iterate over
         # non-builders more than once
         builders = []
         builders_used = []
         for aid, a in self.own_actors.items():
             if self.actor_types[a.actor_type]['can_construct']:
                 if a.current_order[0] == "stop":
                     builders.append(a)
         
         # Now we work out which buildings we can build and who is closest to it
         for building_type, amount in missing.items():
             for i in range(amount):
                 target_pos = base_data['location']
                 
                 closest_builder = None, 9999999
                 for b in builders:
                     if b in builders_used: continue
                     if actor_lib.can_build(
                         builder_type = self.actor_types[b.actor_type],
                         item_type = self.actor_types[building_type],
                         build_lists = self.build_lists,
                     ):
                         # If they are closest we want them to go build it
                         dist = vectors.distance(target_pos, b.pos)
                         
                         if dist < closest_builder[1]:
                             closest_builder = b, dist
                 
                 # Now remove them from the pool and issue the build order
                 if closest_builder[0] != None:
                     builders_used.append(closest_builder[0])
                     self.issue_orders(closest_builder[0].oid, cmd="build", pos=target_pos, target=building_type)
                     
                     base_data['buildings_in_progress'].append([building_type, buildings_in_progress_ttl])
Example #9
0
    def inspect_bases(self):
        # First find out which buildings we are missing
        for base_name, base_data in self.bases.items():
            base_area = (
                base_data['location'][0] - base_data['size'][0],
                base_data['location'][1] - base_data['size'][1],
                base_data['location'][0] + base_data['size'][0],
                base_data['location'][1] + base_data['size'][1],
            )

            buildings_needed = set(base_data['buildings'])

            # Reset this now
            base_data['current_buildings'] = []

            # Get all buildings within this base
            found_buildings = {}
            total_needed = {}
            for b in buildings_needed:
                found_buildings[b] = 0
                total_needed[b] = 0

            for b in base_data['buildings']:
                total_needed[b] += 1

            # Loop through all actors and see what we've got
            for i, a in self.own_actors.items():
                if actor_lib.is_inside(a, base_area):
                    if a.actor_type in buildings_needed:
                        found_buildings[a.actor_type] += 1

                        if a.completion >= 100:
                            base_data['current_buildings'].append(a.oid)

            # Now also loop through all the buildings_in_progress
            # Use a range loop so we can update the list as we go
            for i in range(
                    len(base_data['buildings_in_progress']) - 1, -1, -1):
                b, ttl = base_data['buildings_in_progress'][i]

                if ttl <= 0:
                    del (base_data['buildings_in_progress'][i])
                    continue

                base_data['buildings_in_progress'][i][1] -= 1

                if b in found_buildings:
                    found_buildings[b] += 1

            # Now find out what we are missing
            missing = {}
            for b in buildings_needed:
                m = total_needed[b] - found_buildings[b]
                if m > 0:
                    missing[b] = m

            # None missing? We can stop looking around now
            if missing == {}:
                continue

            # Now find out which builders we can use
            # Narrow down our list of builders so we don't later iterate over
            # non-builders more than once
            builders = []
            builders_used = []
            for aid, a in self.own_actors.items():
                if self.actor_types[a.actor_type]['can_construct']:
                    if a.current_order[0] == "stop":
                        builders.append(a)

            # Now we work out which buildings we can build and who is closest to it
            for building_type, amount in missing.items():
                for i in range(amount):
                    target_pos = base_data['location']

                    closest_builder = None, 9999999
                    for b in builders:
                        if b in builders_used: continue
                        if actor_lib.can_build(
                                builder_type=self.actor_types[b.actor_type],
                                item_type=self.actor_types[building_type],
                                build_lists=self.build_lists,
                        ):
                            # If they are closest we want them to go build it
                            dist = vectors.distance(target_pos, b.pos)

                            if dist < closest_builder[1]:
                                closest_builder = b, dist

                    # Now remove them from the pool and issue the build order
                    if closest_builder[0] != None:
                        builders_used.append(closest_builder[0])
                        self.issue_orders(closest_builder[0].oid,
                                          cmd="build",
                                          pos=target_pos,
                                          target=building_type)

                        base_data['buildings_in_progress'].append(
                            [building_type, buildings_in_progress_ttl])