def _get_target_getters(cls, creep):
        targets = [
            #cls._get_random_nonempty_util_building,  # TODO: balance
            #cls._get_neighboring_nonfull_link,       # TODO: remove that function if miner doesn't use it
        ]
        if creep.room.energyCapacityAvailable < 1300:
            targets.append(cls._get_nearby_construction_site)
            targets.append(cls._get_closest_construction_site)
        else:
            targets.append(
                cls._get_closest_nonempty_util_building
            )
        #print('g_links', g_links, g_links.get)
        #if not g_links or g_links == undefined:
        #    print('warning!!!')
        #    return
        #our_links = g_links.get(creep.room.name)
        #if not our_links.operational():
        if creep.room.controller.level <= 5:
            links = search_room(creep.room, FIND_STRUCTURES, lambda x: x.structureType == STRUCTURE_LINK)
            if links != undefined:
                sources = search_room(creep.room, FIND_SOURCES)
                if len(links) < (len(sources) + 1):
                    targets.extend(
                        [
                            cls._get_random_non_miner_container,
                            cls._get_closest_nonfull_link,
                        ]
                    )
        #if creep.room.controller.level >= 5:  # TODO: if not container, then ANY link will do
        #    targets.append(
        #        #cls._get_closest_link,
        #        cls._get_closest_nonfull_link,
        #    )
        fullest_miner_container = cls._get_fullest_miner_container(creep)

        if fullest_miner_container != undefined and fullest_miner_container.store[RESOURCE_ENERGY] > 0 or creep.room.controller.level >= 6: # and creep.room.name == 'W25N3':
            #print('yeah', creep.name, fullest_miner_container.store[RESOURCE_ENERGY], fullest_miner_container.id)
            targets.append(cls._get_nonfull_terminal)
            targets.append(cls._get_nonfull_storage)
            targets.append(cls._get_nonfull_storage)
        if creep.room.energyCapacity < 1300:
            targets.append(cls._get_nearby_construction_site)
            targets.append(cls._get_closest_construction_site)
        #if creep.room.controller.level >= 5:
        #    targets.append(
        #        cls._get_closest_link,
        #    )
        return targets
Example #2
0
 def spawn_creeps(self):
     room = self.room
     spawn = get_first_spawn(room)
     if not spawn:
         return
     if room.energyCapacityAvailable < 1300 and len(Game.rooms) >= 2:
         return  # we are being bootstrapped by someone else, we hope
     if not spawn.spawning:
         sources = search_room(room, FIND_SOURCES)
         desired_miners = len(sources)
         if room.name == 'W26N3':
             desired_miners =  2*len(sources)
         if len(sources) == 1 and self.creep_registry.count_of_type(room, 'miner') < desired_miners:
             miner_containers, source_to_controller_paths, map_size = self.get_miner_container_positions(sources)
             point = miner_containers[0]
             for s in room.lookForAt(LOOK_STRUCTURES, point.x, point.y):
                 if s.structureType == STRUCTURE_CONTAINER and s.hits >= 1:
                     if room.energyAvailable >= 300:  # wait until source is full (there are no extensions)
                         spawn.createCreep([WORK, WORK, MOVE, MOVE], "", {'cls': 'miner'})
                     return
         max_harvesters = self.ROOM_HARVESTERS[room.name]
         if max_harvesters == undefined:
             max_harvesters = self.MAX_HARVESTERS[len(sources)]
         if (self.creep_registry.count_of_type(room, 'harvester') + 8*self.creep_registry.count_of_type(room, 'upgrader')) < max_harvesters:  # keep spawning them, why not
             if room.energyAvailable >= 250:  # wait until source is full (there are no extensions)
                 spawn.createCreep([WORK, CARRY, MOVE, MOVE], "", {'cls': 'harvester'})
Example #3
0
 def spawn_creeps_in_transition_period(self):
     room = self.room
     spawn = get_first_spawn(room)
     sources = search_room(room, FIND_SOURCES)
     if room.energyCapacityAvailable >= 500:
         if self.creep_registry.count_of_type(
                 room, 'harvester'
         ) < RoomManagerRCL1.MAX_HARVESTERS:  # keep spawning them, why not
             if room.energyAvailable >= 500:
                 spawn.createCreep(
                     [WORK, WORK, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE], "",
                     {'cls': 'harvester'})
     elif room.energyCapacityAvailable >= 450:
         if self.creep_registry.count_of_type(room, 'miner') < len(sources):
             if room.energyAvailable >= 450:
                 spawn.createCreep([WORK, WORK, WORK, WORK, MOVE], "",
                                   {'cls': 'miner'})
         if self.creep_registry.count_of_type(
                 room, 'harvester'
         ) < RoomManagerRCL1.MAX_HARVESTERS:  # keep spawning them, why not
             if room.energyAvailable >= 450:
                 spawn.createCreep(
                     [WORK, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE],
                     "", {'cls': 'harvester'})
     elif room.energyCapacityAvailable >= 350:
         if self.creep_registry.count_of_type(room, 'miner') < len(sources):
             if room.energyAvailable >= 350:
                 spawn.createCreep([WORK, WORK, WORK, MOVE], "",
                                   {'cls': 'miner'})
         if self.creep_registry.count_of_type(
                 room, 'harvester'
         ) < RoomManagerRCL1.MAX_HARVESTERS:  # keep spawning them, why not
             if room.energyAvailable >= 350:
                 spawn.createCreep([WORK, CARRY, CARRY, MOVE, MOVE, MOVE],
                                   "", {'cls': 'harvester'})
     else:
         return RoomManagerRCL1(room, self.creep_registry).spawn_creeps(
         )  # keep RCL1 layout until they build up the extensions
Example #4
0
    def run_build(self):
        # TODO: don't do it every tick
        room = self.room

        # shaped farms first
        if room.energyCapacityAvailable < 550:  # all extensions were not built yet
            #eree
            # ere
            #   r
            #   S

            #self.build_extension(spawn_pos.x,   spawn_pos.y-2)
            #self.build_extension(spawn_pos.x,   spawn_pos.y-3)
            #self.build_extension(spawn_pos.x-1, spawn_pos.y-3)
            #self.build_extension(spawn_pos.x-2, spawn_pos.y-2)
            #self.build_extension(spawn_pos.x-3, spawn_pos.y-3)
            #if self.enable_building:
            #    return
            pass

        #self.build_roads(
        #    [
        #        P(spawn_pos.x,   spawn_pos.y-1),
        #        P(spawn_pos.x-1, spawn_pos.y-2),
        #        P(spawn_pos.x-2, spawn_pos.y-3),
        #    ]
        #)

        sources = search_room(room, FIND_SOURCES)

        miner_containers, source_to_controller_paths, map_size = self.get_miner_container_positions(
            sources)

        spawn = get_first_spawn(room)

        if not spawn or spawn == undefined:
            path = source_to_controller_paths[0]
            if len(source_to_controller_paths) >= 2:
                otherpath = source_to_controller_paths[1]
                if len(source_to_controller_paths[0]) > len(
                        source_to_controller_paths[1]):
                    # actually source2 is closer to controller
                    path = source_to_controller_paths[1]
                    otherpath = source_to_controller_paths[0]
            if len(path) > 2:
                self.build_spawn(path[1].x, path[1].y)
            if room.controller.level >= 7:
                if len(otherpath) > 2:
                    self.build_spawn(otherpath[1].x, otherpath[1].y)

        if spawn is None or spawn == undefined:
            #return  # no spawn yet and no construction site.
            return
        else:
            spawn_pos = spawn.pos

        if room.controller.level == 5 and len(sources) == 2:
            path = room.findPath(sources[0].pos, sources[1].pos,
                                 {'ignoreCreeps': True})
            map_size += len(path) - 2  # route to container, not source
        room_sizes[room] = map_size

        def costCallback(roomName, costMatrix):
            terrain = Game.rooms[roomName].getTerrain()
            around_coords = around_range(room, room.controller.pos.x,
                                         room.controller.pos.y, 1)
            around_coords.extend(
                around_range(room, room.controller.pos.x,
                             room.controller.pos.y, 2))
            walls = []
            for x, y in around_coords:
                if terrain.get(x, y) == 1:
                    walls.append((x, y))
            for wx, wy in walls:
                for x, y in around_range(room, wx, wy, 1):
                    costMatrix.set(x, y, 20)

            #    value = 70
            #        value = 255
            #    costMatrix.set(x, y, value)
            #for x, y in around_range(room, room.controller.pos.x, room.controller.pos.y, 2):
            #    value = 40
            #    if terrain.get(x, y) == 1:
            #        value = 255
            #    costMatrix.set(x, y, value)
            #costMatrix.set(18, 8, 50)

        #PathFinder.use(True)
        # build a container next to controller
        path = room.findPath(
            room.controller.pos,
            spawn_pos,
            {
                'ignoreCreeps': True,
                'costCallback': costCallback,
                'maxRooms': 1,
            },
        )
        controller_container = room.getPositionAt(path[1].x, path[1].y)

        if room.controller.level <= 4:
            self.build_container(path[1].x, path[1].y)

        roads = []
        #if 1:
        #    roads.append(path)
        #    #return

        ignoreRoads = True
        for miner_container in miner_containers:
            path = room.findPath(miner_container, controller_container, {
                'ignoreCreeps': True,
                'ignoreRoads': ignoreRoads
            })
            roads.append(path[0:len(path) - 1])
            path = room.findPath(miner_container, spawn_pos,
                                 {'ignoreCreeps': True})
            roads.append(path[0:len(path) - 1])

        links = Links()
        link_filter = lambda s: (s.structureType == STRUCTURE_LINK)

        self.debug_log('REGISTERING LINKS IN ' + room.name)

        handled = set()
        for what, obj in [
            ('controller', room.controller),
            ('storage', room.storage),
            ('terminal', room.terminal),
                # TODO: mineral link
        ]:
            if obj == undefined:
                self.debug_log(what + ' does not exist in ' + room.name)
                continue
            structures = obj.pos.findInRange(
                FIND_STRUCTURES, 3, filter=link_filter
            )  # TODO: if faith source is close to energy source, this will mess up
            if len(structures) >= 1:
                setattr(links, what + '_id', structures[0].id)
                self.debug_log(what + '_link: ' + structures[0].id)
                handled.add(structures[0].id)
            else:
                self.debug_log(what + ' has no link, apparently')

        for miner_container in miner_containers:
            if miner_container == undefined:
                continue
            #print(miner_container)
            if miner_container.pos != undefined:  # FIXME wtf
                miner_links = miner_container.pos.findInRange(
                    FIND_STRUCTURES, 1, filter=link_filter)
            else:
                miner_links = miner_container.findInRange(FIND_STRUCTURES,
                                                          1,
                                                          filter=link_filter)
            if len(miner_links):
                self.debug_log('miner_link ' + miner_links[0].id + ' ' +
                               miner_container.id)
                links.source_ids.append(miner_links[0].id)
                handled.add(miner_links[0].id)
            else:
                self.debug_log('no miner_link for' + miner_container)

        for link in room.find(FIND_STRUCTURES, filter=link_filter):
            if link == undefined:
                continue
            #self.debug_log('handled', handled, 'link.id', link.id)
            #if link.id == links.controller_id:
            #    continue
            if handled.includes(link.id):
                #self.debug_log(link.id, 'was already handled')
                continue
            self.debug_log('other link: ' + link.id)
            links.other_ids.append(link.id)

        #print('setting links', links, 'in', room)
        g_links[room.name] = links

        #print('road', roads[0][1])
        #room.visual.poly(roads[0][1], {'color': 'ff0000'})
        #print(roads[0][1][0], roads[0][1][len(roads[0][1]-1)])
        #room.getPositionAt(roads[0][1][0].x, roads[0][1][0].y)
        roads.sort(key=lambda road: -1 * len(road))
        #for road in roads:
        #    room.visual.poly([(point.x, point.y) for point in road], {'stroke': '#00ff00'})

        #for s in room.find(FIND_STRUCTURES):
        #    if s.structureType == STRUCTURE_ROAD:
        #        s.destroy()

        built_something = False
        for road in roads:
            for point in road:
                has_road = False
                for s in room.lookForAt(LOOK_STRUCTURES, point.x, point.y):
                    if s.structureType == STRUCTURE_ROAD and s.hits >= 1:
                        has_road = True
                        break
                if not has_road or not self.enable_building:
                    built_something = True
            if built_something:
                self.build_roads(road)
                if self.enable_building:
                    break  # build roads incrementally
Example #5
0
    def spawn_creeps(self):
        room = self.room
        controller = room.controller
        controller_flag = Game.flags[room.name]
        #controller_flag = None
        #for s in room.lookForAt(LOOK_FLAGS, controller.pos.x, controller.pos.y):
        #    controller_flag = s
        #    break
        spawn = get_first_spawn(room)
        print(',,, spawn_creeps() in', room.name)
        if spawn is None or spawn == undefined:
            return  # no spawn yet
        if spawn.spawning:
            return
        if room.energyCapacityAvailable < 1300:  # and len(Game.rooms) >= 2:
            print('skipping spawning in', room.name,
                  'because we are bootstrapped by other rooms')
            return  # we are being bootstrapped by someone else, we hope
        if room.energyCapacityAvailable < 550:  # extensions were not built yet
            return self.spawn_creeps_in_transition_period()

        # XXX XXX XXX // big temp section \\

        if controller_flag != undefined:
            print('we have a controller flag!')
            claim_target = controller_flag.memory['claim']
            if claim_target != undefined:
                print('and a claim target!')
                #if target_time <= Game.time and Game.time <= (target_time + 600):
                target_room = Game.rooms[claim_target]
                if target_room == undefined or not target_room.controller.my:
                    cls = 'claimer'
                    # claim mode
                    claimer_name = claim_target + '_' + cls
                    if Game.creeps[
                            claimer_name] == undefined and room.energyCapacityAvailable > 850:
                        print('and we spawn a claimer, whoooo!!')
                    spawn.spawnCreep(
                        [CLAIM, MOVE, MOVE, MOVE, MOVE, MOVE], claimer_name,
                        {"memory": {
                            "cls": cls,
                            "room": claim_target
                        }})
                elif target_room != undefined or target_room.energyCapacityAvailable < 1300:
                    # build and boost mode
                    if target_room.energyCapacityAvailable >= 1300:
                        controller_flag.remove()  # ok we are done
                    elif Game.map.getRoomLinearDistance(
                            room.name, target_room.name) >= 3:
                        # long distance higher CPU but move fast
                        miner_spec = [
                            WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                            CARRY, MOVE, MOVE, MOVE, MOVE
                        ]
                    else:
                        # short distance low CPU but move slow
                        miner_spec = [
                            WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                            WORK, WORK, CARRY, CARRY, MOVE, MOVE
                        ]

                    if room.energyAvailable < room.energyCapacityAvailable:  # only help other room if our room doesn't need much
                        pass
                    elif Game.creeps[
                            claim_target +
                            '_bminer1'] == undefined:  # or Game.creeps[claim_target + '_bminer1'].ticksToLive:
                        spawn.spawnCreep(
                            miner_spec, claim_target + "_bminer1",
                            {"memory": {
                                "cls": "miner",
                                "room": claim_target
                            }})
                    elif Game.creeps[claim_target + '_bminer2'] == undefined:
                        spawn.spawnCreep(
                            miner_spec, claim_target + "_bminer2",
                            {"memory": {
                                "cls": "miner",
                                "room": claim_target
                            }})

                    elif Game.creeps[claim_target + '_bbuilder1'] == undefined:
                        spawn.spawnCreep([
                            WORK, WORK, WORK, WORK, WORK, CARRY, CARRY, CARRY,
                            CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE
                        ], claim_target + "_bbuilder1", {
                            "memory": {
                                "cls": "builder",
                                "room": claim_target
                            }
                        })
                    elif Game.creeps[claim_target + '_bbuilder2'] == undefined:
                        spawn.spawnCreep([
                            WORK, WORK, WORK, WORK, WORK, CARRY, CARRY, CARRY,
                            CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE
                        ], claim_target + "_bbuilder2", {
                            "memory": {
                                "cls": "builder",
                                "room": claim_target
                            }
                        })

                    elif Game.creeps[claim_target + '_bhauler1'] == undefined:
                        spawn.spawnCreep([
                            WORK, WORK, CARRY, CARRY, CARRY, CARRY, CARRY,
                            CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE
                        ], claim_target + "_bhauler1", {
                            "memory": {
                                "cls": "hauler",
                                "room": claim_target
                            }
                        })
                    elif Game.creeps[claim_target + '_bhauler2'] == undefined:
                        spawn.spawnCreep([
                            WORK, WORK, CARRY, CARRY, CARRY, CARRY, CARRY,
                            CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE
                        ], claim_target + "_bhauler2", {
                            "memory": {
                                "cls": "hauler",
                                "room": claim_target
                            }
                        })
                    elif Game.creeps[claim_target + '_bhauler3'] == undefined:
                        spawn.spawnCreep([
                            WORK, WORK, CARRY, CARRY, CARRY, CARRY, CARRY,
                            CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE
                        ], claim_target + "_bhauler3", {
                            "memory": {
                                "cls": "hauler",
                                "room": claim_target
                            }
                        })
                    #elif Game.creeps[claim_target + '_bhauler4'] == undefined:
                    #    spawn.spawnCreep([WORK, WORK, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE], claim_target + "_bhauler4", {"memory": {"cls": "hauler", "room": claim_target}})

                    elif Game.creeps[claim_target +
                                     '_bupgrader1'] == undefined:
                        spawn.spawnCreep([
                            WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                            WORK, WORK, CARRY, CARRY, MOVE, MOVE
                        ], claim_target + "_bupgrader1", {
                            "memory": {
                                "cls": "upgrader",
                                "room": claim_target
                            }
                        })
                    elif Game.creeps[claim_target +
                                     '_bupgrader2'] == undefined:
                        spawn.spawnCreep([
                            WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                            WORK, WORK, CARRY, CARRY, MOVE, MOVE
                        ], claim_target + "_bupgrader2", {
                            "memory": {
                                "cls": "upgrader",
                                "room": claim_target
                            }
                        })
                    #elif Game.creeps[claim_target + '_bupgrader3'] == undefined:
                    #    spawn.spawnCreep([WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, CARRY, CARRY, MOVE, MOVE], claim_target + "_bupgrader3", {"memory": {"cls": "upgrader", "room": claim_target}})
                    #elif Game.creeps[claim_target + '_bupgrader4'] == undefined:
                    #    spawn.spawnCreep([WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, CARRY, CARRY, MOVE, MOVE], claim_target + "_bupgrader4", {"memory": {"cls": "upgrader", "room": claim_target}})
                    #elif Game.creeps[claim_target + '_bupgrader5'] == undefined:
                    #    spawn.spawnCreep([WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, CARRY, CARRY, MOVE, MOVE], claim_target + "_bupgrader5", {"memory": {"cls": "upgrader", "room": claim_target}})

        # XXX XXX XXX \\ big temp section //

        to_construct = [
            s.progressTotal - s.progress
            for s in room.find(FIND_CONSTRUCTION_SITES)
        ]
        to_construct_sum = sum(to_construct)
        builders = self.creep_registry.count_of_type(room, 'builder')
        miners = self.creep_registry.count_of_type(room, 'miner')
        haulers = self.creep_registry.count_of_type(room, 'hauler')
        dropped_sum = sum(
            [r.amount for r in room.find(FIND_DROPPED_RESOURCES)])
        size = room_sizes[room]
        if size == undefined:  # TODO: fill it aggresively, don't wait
            size = 20
        #print('room size', room, size)
        sources = search_room(room, FIND_SOURCES)
        desired_haulers = max(1,
                              int(size / 7))  # TODO: can use less larger ones

        if room.controller.level == 4 and room.energyCapacityAvailable >= 1300:
            desired_haulers = desired_haulers / 2
        elif room.controller.level == 5:  # TODO: actually we should see if links are up and if we have miners with CARRY
            if len(sources) == 2:
                desired_haulers = max(2, desired_haulers / 2)
            elif len(sources) == 1:
                desired_haulers = 1
            else:
                print('WARING: weird number of sources in a plannable room?')
        elif room.controller.level >= 6:
            desired_haulers = 1  # with creeps fully optimized for CPU a single filler is not enough
            #if room.energyCapacityAvailable - room.energyAvailable >= 2401:
            #    desired_haulers = 2  # with creeps fully optimized for CPU just one filler is not enough
            #    Game.notify(
            #        'Room ' + room.name + ' was low on energy (' + str(room.energyCapacityAvailable) + ') and needed extra haulers',
            #        #1,  # group these notifications for X min
            #        60,  # group these notifications for X min
            #    )
        source_near_controller = room.controller.pos.findInRange(
            FIND_SOURCES, 2)  # TODO: can be made smarter
        if to_construct_sum > 12000 and builders < 5 and miners >= 1 and len(sources) >= 2 or \
           to_construct_sum > 9000 and builders < 4 and miners >= 1 and len(sources) >= 2 or \
           to_construct_sum > 6000 and builders < 3 and miners >= 1 and len(sources) >= 2 or \
           to_construct_sum > 3000 and builders < 2 or \
           to_construct_sum > 0 and builders < 1:
            # builders first to make containers for mining
            to_construct_max = max(to_construct)
            to_construct_avg = sum(to_construct) / len(to_construct)
            if room.energyAvailable >= 1000:
                if to_construct_max >= 5001:  # terminal and storage
                    parts = [
                        WORK, WORK, WORK, WORK, WORK, CARRY, CARRY, CARRY,
                        CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE
                    ]
                elif to_construct_avg >= 5001:  # like a tower or spawn
                    parts = [
                        WORK, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE,
                        MOVE, MOVE
                    ]
                else:  # roads, extensions, containers
                    parts = [WORK, WORK, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE]
                spawn.createCreep(parts, "", {'cls': 'builder'})
            elif room.energyAvailable >= 550:
                if to_construct_max >= 5001:  # terminal and storage
                    parts = [WORK, WORK, WORK, CARRY, MOVE, MOVE, MOVE, MOVE]
                elif to_construct_avg >= 5001:  # like a tower or spawn
                    parts = [
                        WORK, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE,
                        MOVE, MOVE
                    ]
                else:  # roads, extensions, containers
                    parts = [WORK, WORK, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE]
                spawn.createCreep(parts, "", {'cls': 'builder'})
        elif miners < len(sources):
            if room.controller.level <= 4:
                parts = []
                alt_cost = 0
                if room.energyAvailable >= 2200:
                    parts = [
                        WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                        WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                        WORK, WORK, MOVE, MOVE, MOVE, MOVE
                    ]
                    alt_cost = 2250
                elif room.energyAvailable >= 1650:
                    parts = [
                        WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                        WORK, WORK, WORK, WORK, WORK, WORK, MOVE, MOVE, MOVE
                    ]
                    alt_cost = 1700
                elif room.energyAvailable >= 1100:
                    parts = [
                        WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                        WORK, MOVE, MOVE
                    ]
                    alt_cost = 1150
                elif room.energyAvailable >= 550:
                    parts = [WORK, WORK, WORK, WORK, WORK, MOVE]
                    alt_cost = 600
                if len(parts) and source_near_controller:
                    if room.energyAvailable >= alt_cost:
                        parts.append(CARRY)
                if parts:
                    spawn.createCreep(parts, "", {'cls': 'miner'})
            else:  # link miners
                if room.energyAvailable >= 3700 and False:  # this one is overoptimized for CPU, consumes a lot of energy
                    spawn.createCreep(
                        [
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            CARRY,
                            CARRY,
                            CARRY,
                            CARRY,
                            CARRY,
                            CARRY,
                            CARRY,
                            CARRY,
                            MOVE,
                            MOVE,
                            MOVE,
                            MOVE,
                            MOVE,
                            MOVE,  # TODO: they should spawn on the position and never move
                        ],
                        "",
                        {'cls': 'miner'})
                elif room.energyAvailable >= 3600 and False:  # this too
                    spawn.createCreep(
                        [  # TODO: those should be calculated by math from energyAvailable, not templated
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            CARRY,
                            CARRY,
                            CARRY,
                            CARRY,
                            CARRY,
                            CARRY,
                            MOVE,
                            MOVE,
                            MOVE,
                            MOVE,
                            MOVE,
                            MOVE,
                        ],
                        "",
                        {'cls': 'miner'})
                elif room.energyAvailable >= 2400:
                    spawn.createCreep(
                        [
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            WORK,
                            CARRY,
                            CARRY,
                            CARRY,
                            CARRY,
                            MOVE,
                            MOVE,
                            MOVE,
                            MOVE,  # TODO: could save 200*2/1500, 400 per creep life, if it didn't move
                        ],
                        "",
                        {'cls': 'miner'})
                elif room.energyAvailable >= 1800:
                    spawn.createCreep([
                        WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                        WORK, WORK, WORK, WORK, WORK, WORK, CARRY, CARRY,
                        CARRY, MOVE, MOVE, MOVE
                    ], "", {'cls': 'miner'})
                elif room.energyAvailable >= 1200:
                    spawn.createCreep([
                        WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                        WORK, CARRY, CARRY, MOVE, MOVE
                    ], "", {'cls': 'miner'})
                elif room.energyAvailable >= 600:
                    spawn.createCreep(
                        [WORK, WORK, WORK, WORK, WORK, CARRY, MOVE], "",
                        {'cls': 'miner'})
                elif room.energyAvailable >= 550 and room.controller.level <= 4:  # non-link miners only for non-link rooms
                    spawn.createCreep([WORK, WORK, WORK, WORK, WORK, MOVE], "",
                                      {'cls': 'miner'})
        #elif self.creep_registry.count_of_type(room, 'hauler') < 2: #TODO len(room.sources):  # TODO: ? 2
        #    if room.energyAvailable >= 550:
        #        spawn.createCreep([WORK, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE], "", {'cls': 'hauler'})
        #elif dropped_sum > 5000 and haulers < 5 or \
        #     dropped_sum > 1000 and haulers < 4 or \
        #     dropped_sum > 50 and haulers < 3 or \
        #     haulers < 2:
        elif haulers < desired_haulers:
            if room.energyAvailable >= 1100:
                parts = [
                    WORK, WORK, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY,
                    CARRY, CARRY, MOVE, MOVE, MOVE, MOVE, MOVE
                ]
                spawn.createCreep(parts, "", {'cls': 'hauler'})
                return
            if self.creep_registry.count_of_type(
                    room, 'harvester') + self.creep_registry.count_of_type(
                        room, 'hauler'
                    ) >= 1 and room.energyCapacityAvailable >= 1100:
                return  # wait for refill
            if room.energyAvailable >= 550:
                # TODO: scale it to the room size
                #parts = [CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE, MOVE]
                parts = [
                    WORK, CARRY, CARRY, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE
                ]
                spawn.createCreep(parts, "", {'cls': 'hauler'})
                return

        if to_construct > 300:
            return

        # claimer

        ###################################################
        claimername = room.name + 'cla'
        if room.name == 'W27N1' and False:
            if room.energyCapacityAvailable >= 3250 and Game.creeps[
                    claimername] == undefined:
                e = Game.spawns['W27N1-2'].spawnCreep(  # TODO: use spawnCreep everywhere
                    [
                        CLAIM, CLAIM, CLAIM, CLAIM, CLAIM,
                        MOVE, MOVE, MOVE, MOVE, MOVE,
                    ],
                    claimername,
                    {
                        'memory': {'cls': 'claimer', 'room': 'W25N3'}, #, 'wp_room': 'W26N2', 'wp_room2': 'W26N3'},
                        'directions': [BOTTOM],
                    }
                )
                print('============= YEAH', e)
            else:
                print('============= NOPE')
        ###################################################

        # upgraders

        #  eee
        # 12fe
        # 1M2e
        # E11
        #
        # E: source
        # M: miner
        # f: filler
        # e: extension
        # 1: accessible only to Miner: tower, terminal
        # 2: accessible to both Miner and Filler: spawn, storage
        # please note that it would be best for terminal and storage to be accessible. Also Spawn(2) must be accessible.
        if source_near_controller:
            if miners >= 1:
                pass
            miners = self.creep_registry.list_of_type(room, 'miner')
            for miner in miners:
                if miner.pos.inRangeTo(room.controller, 3):
                    carries = part_count(miner, 'carry')
                    if carries >= 1:
                        print('do not spawn an upgrader in', room.name,
                              'as we expect the miner to take care of it')
                        return
        spawn = get_controller_spawn(room)
        if spawn.spawning:
            return  # spawn is busy
        if to_construct_sum > 2000 and room.controller.ticksToDowngrade > 1000:
            return  # we have stuff to build, lets not use energy for upgrade right now

        #if room.controller.ticksToDowngrade > 1000:
        #    # XXX: temporarily disable spawning upgraders so that we can build new rooms
        #    return

        #if room.controller.level == 8:
        #    print('not spawning an upgrader because it was disabled')
        #    return
        if room.energyCapacityAvailable >= 100 * 15 + 50 * 3 + 50 * 5:
            spawn_it = False
            if self.creep_registry.count_of_type(room, 'upgrader') < 1:
                spawn_it = True
            else:
                prespawn = 23 * CREEP_SPAWN_TIME
                for upgrader in self.creep_registry.list_of_type(
                        room, 'upgrader'
                ):  # this behaves funny, 'undefined', there is only one, lets go
                    if upgrader.ticksToLive <= prespawn:
                        spawn_it = True
                    break
            if spawn_it:
                newname = room.name + 'upg'
                while Game.creeps[newname] != undefined:
                    newname += '1'
                spawn.spawnCreep(  # TODO: use spawnCreep everywhere
                    [
                        WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK,
                        CARRY, CARRY, CARRY,  # TODO: get even more?
                        MOVE, MOVE, MOVE, MOVE, MOVE,  # TODO: could save 250 energy / 1500 tics here if we spawned the guy and immediately moved him where he belongs
                    ],
                    newname,  # TODO: uhhhh
                    {
                        'memory': {'cls': 'upgrader'},
                        # TODO: take energy from spawns first
                        # TODO: 'directions': [TOP_RIGHT],
                    }
                )
            if room.controller.level == 8:
                return
        elif room.energyCapacityAvailable >= 950:
            if self.creep_registry.count_of_type(room,
                                                 'upgrader') < len(sources):
                spawn.createCreep([
                    WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, CARRY,
                    MOVE, MOVE
                ], "", {'cls': 'upgrader'})
            elif self.creep_registry.count_of_type(
                    room,
                    'upgrader') < len(sources) + 1 and dropped_sum >= 3000:
                spawn.createCreep([
                    WORK, WORK, WORK, WORK, WORK, WORK, WORK, WORK, CARRY,
                    MOVE, MOVE
                ], "", {'cls': 'upgrader'})
                Game.notify(
                    'spawning additional upgrader in room ' + room.name +
                    ' because ' + str(dropped_sum) +
                    ' energy is laying on the ground', 60)
        elif room.energyCapacityAvailable >= 650:
            if self.creep_registry.count_of_type(
                    room, 'upgrader') < (len(sources) + 1):
                spawn.createCreep(
                    [WORK, WORK, WORK, WORK, WORK, CARRY, MOVE, MOVE], "",
                    {'cls': 'upgrader'})
        elif room.energyCapacityAvailable >= 550:
            if self.creep_registry.count_of_type(
                    room, 'upgrader') < 2 * len(sources):
                spawn.createCreep([WORK, WORK, WORK, WORK, CARRY, MOVE, MOVE],
                                  "", {'cls': 'upgrader'})
    def _run(self):
        super()._run()
        creep = self.creep
        room = creep.room
        sources = search_room(room, FIND_SOURCES)
        containers = search_room(
            room, FIND_STRUCTURES,
            lambda x: x.structureType == STRUCTURE_CONTAINER)
        thing = get_thing_at_coordinates(
            containers, creep.pos.x, creep.pos.y)  # TODO save CPU via lookAt
        flag = room.lookForAt(LOOK_FLAGS, creep.pos.x, creep.pos.y)
        if thing or flag != undefined:
            for source in sources:
                if creep.pos.isNearTo(source):
                    #print(creep, source.ticksToRegeneration, source.ticksToRegeneration % (works/5) == 0)
                    actions = []
                    #if creep.store.getCapacity(RESOURCE_ENERGY) > 0 and creep.store[RESOURCE_ENERGY] > 0:
                    #    actions.append(ScheduledAction.drop(creep, RESOURCE_ENERGY))
                    #if creep.store.getCapacity(RESOURCE_ENERGY) > 0 and creep.store.getFreeCapacity(RESOURCE_ENERGY) == 0:
                    #    for s in creep.pos.findInRange(FIND_MY_STRUCTURES, 1):
                    #        if s.structureType != STRUCTURE_LINK:
                    #            continue
                    #        if s.store.getFreeCapacity(RESOURCE_ENERGY) > 0:
                    #            actions.append(
                    #                ScheduledAction.transfer(creep, s, RESOURCE_ENERGY, priority=80)
                    #            )
                    #        break  # only handle one link
                    dropped = self._get_nearby_dropped_resource(creep)
                    if dropped:
                        dropped = [s for s in dropped if s.pos != creep.pos]
                        if dropped is not None and dropped != undefined:
                            actions.append(
                                ScheduledAction.pickup(creep, dropped[0],
                                                       lambda: 0))
                    if self._should_mine(source):
                        miner_container = None
                        structures = room.lookForAt(LOOK_STRUCTURES,
                                                    creep.pos.x, creep.pos.y)
                        if structures:
                            for structure in structures:
                                if structure.structureType == STRUCTURE_CONTAINER:
                                    miner_container = structure
                        if source.energy != 0 and (
                                creep.store.getFreeCapacity(RESOURCE_ENERGY) >=
                                1 or creep.store.getCapacity(RESOURCE_ENERGY)
                                == 0 or
                            (miner_container and miner_container.store.
                             getFreeCapacity(RESOURCE_ENERGY) >= 1)):
                            actions.append(
                                ScheduledAction.harvest(creep, source))
                        # NOTE: this requires EasyCreep
                        if creep.store[
                                RESOURCE_ENERGY] > 32:  # TODO appropriate value
                            repair = self._get_nearby_repair_action()
                            if len(repair) and Game.time % 10 == 0:
                                a = ScheduledAction.repair(creep, repair)
                                a.priority = 20
                                actions.append(a)
                            else:
                                build = self._get_nearby_build_action()
                                if build:
                                    actions.append(
                                        ScheduledAction.build(creep,
                                                              build,
                                                              priority=20))
                            if creep.room.controller.pos.inRangeTo(
                                    creep.pos.x, creep.pos.y, 3):
                                to_construct = [
                                    s.progressTotal - s.progress
                                    for s in room.find(FIND_CONSTRUCTION_SITES)
                                ]
                                if to_construct == 0:
                                    actions.append(
                                        ScheduledAction.upgradeController(
                                            creep, creep.room.controller))
                    transfer_to_link = self._get_transfer_to_link_actions(
                        creep, source)
                    if len(transfer_to_link) >= 1:
                        actions.extend(transfer_to_link)
                    else:
                        util = self._get_neighboring_nonfull_util(creep)
                        if util:
                            a = make_transfer_action(creep, util)
                            if a:
                                return [a]
                    return actions
        else:  # we are not on a container
            pass

        for source in sources:
            path = creep.room.findPath(source.pos, creep.room.controller.pos,
                                       {'ignoreCreeps': True})
            if len(path) >= 2:
                where = path[0]
                if creep.pos.isEqualTo(where.x, where.y):
                    # mine regardless of whether there is a container or not
                    # other creeps will come and pick it up, use it to build the container
                    actions = []
                    if self._should_mine(source):
                        actions.append(ScheduledAction.harvest(creep, source))
                    transfer_to_link = self._get_transfer_to_link_actions(
                        creep, source)
                    if len(transfer_to_link) >= 1:
                        actions.extend(transfer_to_link)
                    return actions
            else:
                container = get_close_structure(source.pos, 1,
                                                STRUCTURE_CONTAINER)
                if container != undefined:
                    where = container.pos
                else:
                    where = path[0]  # XXX ?

            who = room.lookForAt(LOOK_CREEPS, where.x, where.y)
            actions = []
            if len(who) >= 1:
                # some other creep is currently there
                if not who[0].my:
                    continue
                if who[0].memory.cls == 'miner':  # and it's a miner!
                    continue  # lets try another source
                elif who[0].pos.isNearTo(creep.pos):
                    actions.append(ScheduledAction.moveTo(
                        who[0],
                        creep.pos,
                    ))
                    #Game.notify(
                    print(
                        'swapping creeps at a mining station in ' +
                        creep.room.name + ', ' + str(who[0]) + ' for ' +
                        creep.name,
                        30,
                    )
            actions.append(
                ScheduledAction.moveTo(creep,
                                       room.getPositionAt(where.x, where.y)))
            return actions
        Game.notify(
            'WARNING: ' + creep.name + ' is a miner with no source to mine',
            30)
        return []