elif self.structures(UnitTypeId.ASSIMILATOR) and not self.already_pending(UnitTypeId.ASSIMILATOR):
for vespene in self.vespene_geyser.closer_than(15, nexus):
if self.can_afford(UnitTypeId.ASSIMILATOR):
await self.build(UnitTypeId.ASSIMILATOR, vespene)
I asked AI and my tutor, no one can solve this problems.
can anybody help me!
KeyError: 4444
2026-04-11 19:22:12.777 | INFO | sc2.sc2process:_close_connection:243 - Closing connection at 49774...
2026-04-11 19:22:12.778 | INFO | sc2.sc2process:kill_all:36 - kill_switch: Process cleanup for 12 processes
KeyError Traceback (most recent call last)
Cell In[33], line 1
----> 1 run_game(maps.get("2000AtmospheresAIE"), [
2 Bot(Race.Protoss, WorkerRushBot()),
3 Computer(Race.Zerg, Difficulty.Hard)
4 ], realtime=False)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:531, in run_game(map_settings, players, realtime, portconfig, save_replay_as, game_time_limit, rgb_render_config, random_seed, sc2_version, disable_fog)
529 assert all(isinstance(r, Result) for r in result)
530 else:
--> 531 result = asyncio.run(
532 _host_game(
533 map_settings,
534 players,
535 realtime=realtime,
536 portconfig=portconfig,
537 save_replay_as=save_replay_as,
538 game_time_limit=game_time_limit,
539 rgb_render_config=rgb_render_config,
540 random_seed=random_seed,
541 sc2_version=sc2_version,
542 disable_fog=disable_fog,
543 )
544 )
545 assert isinstance(result, Result)
546 return result
File ~\miniconda3\envs\Starcraft\lib\site-packages\nest_asyncio.py:30, in _patch_asyncio..run(main, debug)
28 task = asyncio.ensure_future(main)
29 try:
---> 30 return loop.run_until_complete(task)
31 finally:
32 if not task.done():
File ~\miniconda3\envs\Starcraft\lib\site-packages\nest_asyncio.py:98, in _patch_loop..run_until_complete(self, future)
95 if not f.done():
96 raise RuntimeError(
97 'Event loop stopped before Future completed.')
---> 98 return f.result()
File ~\miniconda3\envs\Starcraft\lib\asyncio\futures.py:201, in Future.result(self)
199 self.__log_traceback = False
200 if self._exception is not None:
--> 201 raise self._exception.with_traceback(self._exception_tb)
202 return self._result
File ~\miniconda3\envs\Starcraft\lib\asyncio\tasks.py:232, in Task.__step(failed resolving arguments)
228 try:
229 if exc is None:
230 # We use the send method directly, because coroutines
231 # don't have __iter__ and __next__ methods.
--> 232 result = coro.send(None)
233 else:
234 result = coro.throw(exc)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:371, in _host_game(map_settings, players, realtime, portconfig, save_replay_as, game_time_limit, rgb_render_config, random_seed, sc2_version, disable_fog)
368 if isinstance(players[0], Bot) and getattr(players[0].ai, "raw_affects_selection", None) is not None:
369 client.raw_affects_selection = players[0].ai.raw_affects_selection
--> 371 result = await _play_game(players[0], client, realtime, portconfig, game_time_limit, rgb_render_config)
372 if client.save_replay_path is not None:
373 await client.save_replay(client.save_replay_path)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:230, in _play_game(player, client, realtime, portconfig, game_time_limit, rgb_render_config)
228 result = await _play_game_human(client, player_id, realtime, game_time_limit)
229 else:
--> 230 result = await _play_game_ai(client, player_id, player.ai, realtime, game_time_limit)
232 logger.info(
233 f"Result for player {player_id} - {player.name if player.name else str(player)}: "
234 f"{result.name if isinstance(result, Result) else result}"
235 )
237 return result
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:200, in _play_game_ai(client, player_id, ai, realtime, game_time_limit)
197 proto_game_info = await client._execute(game_info=sc_pb.RequestGameInfo())
198 ai._prepare_step(gs, proto_game_info)
--> 200 await run_bot_iteration(iteration) # Main bot loop
202 if not realtime:
203 if not client.in_game: # Client left (resigned) the game
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:160, in _play_game_ai..run_bot_iteration(iteration)
158 # In on_step various errors can occur - log properly
159 try:
--> 160 await ai.on_step(iteration)
161 except (AttributeError,) as e:
162 logger.exception(f"Caught exception: {e}")
Cell In[32], line 72, in WorkerRushBot.on_step(self, iteration)
70 elif not self.structures(UnitTypeId.GATEWAY):
71 if self.can_afford(UnitTypeId.GATEWAY):
---> 72 await self.build(UnitTypeId.GATEWAY, near=self.structures(UnitTypeId.PYLON).closest_to(nexus))
74 # 🟡 Cybernetic Core(控制核心)
75 elif not self.structures(UnitTypeId.CYBERNETICSCORE):
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\bot_ai.py:970, in BotAI.build(self, building, near, max_distance, build_worker, random_alternative, placement_step)
968 if position is None:
969 return False
--> 970 builder = build_worker or self.select_build_worker(near)
971 if builder is None:
972 return False
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\bot_ai.py:616, in BotAI.select_build_worker(self, pos, force)
602 def select_build_worker(self, pos: Unit | Point2, force: bool = False) -> Unit | None:
603 """Select a worker to build a building with.
604
605 Example::
(...)
613 :param pos:
614 :param force:"""
615 workers = (
--> 616 self.workers.filter(lambda w: (w.is_gathering or w.is_idle) and w.distance_to(pos) < 20) or self.workers
617 )
618 if workers:
619 for worker in workers.sorted_by_distance_to(pos).prefer_idle:
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\units.py:486, in Units.filter(self, pred)
466 """Filters the current Units object and returns a new Units object.
467
468 Example::
(...)
483 :param pred:
484 """
485 assert callable(pred), "Function is not callable"
--> 486 return self.subgroup(filter(pred, self))
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\units.py:463, in Units.subgroup(self, units)
458 def subgroup(self, units: Iterable[Unit]) -> Units:
459 """Creates a new mutable Units object from Units or list object.
460
461 :param units:
462 """
--> 463 return Units(units, self._bot_object)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\units.py:29, in Units.init(self, units, bot_object)
24 def init(self, units: Iterable[Unit], bot_object: BotAI) -> None:
25 """
26 :param units:
27 :param bot_object:
28 """
---> 29 super().init(units)
30 self._bot_object = bot_object
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\bot_ai.py:616, in BotAI.select_build_worker..(w)
602 def select_build_worker(self, pos: Unit | Point2, force: bool = False) -> Unit | None:
603 """Select a worker to build a building with.
604
605 Example::
(...)
613 :param pos:
614 :param force:"""
615 workers = (
--> 616 self.workers.filter(lambda w: (w.is_gathering or w.is_idle) and w.distance_to(pos) < 20) or self.workers
617 )
618 if workers:
619 for worker in workers.sorted_by_distance_to(pos).prefer_idle:
File ~\miniconda3\envs\Starcraft\lib\functools.py:981, in cached_property.get(self, instance, owner)
979 val = cache.get(self.attrname, _NOT_FOUND)
980 if val is _NOT_FOUND:
--> 981 val = self.func(instance)
982 try:
983 cache[self.attrname] = val
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:1078, in Unit.is_gathering(self)
1074 @cached_property
1075 def is_gathering(self) -> bool:
1076 """Checks if a unit is on its way to a mineral field or vespene geyser to mine.
1077 Only works for own units."""
-> 1078 return self.is_using_ability(IS_GATHERING)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:1050, in Unit.is_using_ability(self, abilities)
1047 def is_using_ability(self, abilities: AbilityId | set[AbilityId]) -> bool:
1048 """Check if the unit is using one of the given abilities.
1049 Only works for own units."""
-> 1050 if not self.orders:
1051 return False
1052 if isinstance(abilities, AbilityId):
File ~\miniconda3\envs\Starcraft\lib\functools.py:981, in cached_property.get(self, instance, owner)
979 val = cache.get(self.attrname, _NOT_FOUND)
980 if val is _NOT_FOUND:
--> 981 val = self.func(instance)
982 try:
983 cache[self.attrname] = val
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:1029, in Unit.orders(self)
1026 """Returns the a list of the current orders."""
1027 # TODO: add examples on how to use unit orders
1028 # pyrefly: ignore
-> 1029 return [UnitOrder.from_proto(order, self._bot_object) for order in self._proto.orders]
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:1029, in (.0)
1026 """Returns the a list of the current orders."""
1027 # TODO: add examples on how to use unit orders
1028 # pyrefly: ignore
-> 1029 return [UnitOrder.from_proto(order, self._bot_object) for order in self._proto.orders]
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:95, in UnitOrder.from_proto(cls, proto, bot_object)
92 elif proto.HasField("target_unit_tag"):
93 target = proto.target_unit_tag
94 return cls(
---> 95 ability=bot_object.game_data.abilities[proto.ability_id],
96 target=target,
97 progress=proto.progress,
98 )
KeyError: 4444
elif self.structures(UnitTypeId.ASSIMILATOR) and not self.already_pending(UnitTypeId.ASSIMILATOR):
for vespene in self.vespene_geyser.closer_than(15, nexus):
if self.can_afford(UnitTypeId.ASSIMILATOR):
await self.build(UnitTypeId.ASSIMILATOR, vespene)
I asked AI and my tutor, no one can solve this problems.
can anybody help me!
KeyError: 4444
2026-04-11 19:22:12.777 | INFO | sc2.sc2process:_close_connection:243 - Closing connection at 49774...
2026-04-11 19:22:12.778 | INFO | sc2.sc2process:kill_all:36 - kill_switch: Process cleanup for 12 processes
KeyError Traceback (most recent call last)
Cell In[33], line 1
----> 1 run_game(maps.get("2000AtmospheresAIE"), [
2 Bot(Race.Protoss, WorkerRushBot()),
3 Computer(Race.Zerg, Difficulty.Hard)
4 ], realtime=False)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:531, in run_game(map_settings, players, realtime, portconfig, save_replay_as, game_time_limit, rgb_render_config, random_seed, sc2_version, disable_fog)
529 assert all(isinstance(r, Result) for r in result)
530 else:
--> 531 result = asyncio.run(
532 _host_game(
533 map_settings,
534 players,
535 realtime=realtime,
536 portconfig=portconfig,
537 save_replay_as=save_replay_as,
538 game_time_limit=game_time_limit,
539 rgb_render_config=rgb_render_config,
540 random_seed=random_seed,
541 sc2_version=sc2_version,
542 disable_fog=disable_fog,
543 )
544 )
545 assert isinstance(result, Result)
546 return result
File ~\miniconda3\envs\Starcraft\lib\site-packages\nest_asyncio.py:30, in _patch_asyncio..run(main, debug)
28 task = asyncio.ensure_future(main)
29 try:
---> 30 return loop.run_until_complete(task)
31 finally:
32 if not task.done():
File ~\miniconda3\envs\Starcraft\lib\site-packages\nest_asyncio.py:98, in _patch_loop..run_until_complete(self, future)
95 if not f.done():
96 raise RuntimeError(
97 'Event loop stopped before Future completed.')
---> 98 return f.result()
File ~\miniconda3\envs\Starcraft\lib\asyncio\futures.py:201, in Future.result(self)
199 self.__log_traceback = False
200 if self._exception is not None:
--> 201 raise self._exception.with_traceback(self._exception_tb)
202 return self._result
File ~\miniconda3\envs\Starcraft\lib\asyncio\tasks.py:232, in Task.__step(failed resolving arguments)
228 try:
229 if exc is None:
230 # We use the
sendmethod directly, because coroutines231 # don't have
__iter__and__next__methods.--> 232 result = coro.send(None)
233 else:
234 result = coro.throw(exc)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:371, in _host_game(map_settings, players, realtime, portconfig, save_replay_as, game_time_limit, rgb_render_config, random_seed, sc2_version, disable_fog)
368 if isinstance(players[0], Bot) and getattr(players[0].ai, "raw_affects_selection", None) is not None:
369 client.raw_affects_selection = players[0].ai.raw_affects_selection
--> 371 result = await _play_game(players[0], client, realtime, portconfig, game_time_limit, rgb_render_config)
372 if client.save_replay_path is not None:
373 await client.save_replay(client.save_replay_path)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:230, in _play_game(player, client, realtime, portconfig, game_time_limit, rgb_render_config)
228 result = await _play_game_human(client, player_id, realtime, game_time_limit)
229 else:
--> 230 result = await _play_game_ai(client, player_id, player.ai, realtime, game_time_limit)
232 logger.info(
233 f"Result for player {player_id} - {player.name if player.name else str(player)}: "
234 f"{result.name if isinstance(result, Result) else result}"
235 )
237 return result
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:200, in _play_game_ai(client, player_id, ai, realtime, game_time_limit)
197 proto_game_info = await client._execute(game_info=sc_pb.RequestGameInfo())
198 ai._prepare_step(gs, proto_game_info)
--> 200 await run_bot_iteration(iteration) # Main bot loop
202 if not realtime:
203 if not client.in_game: # Client left (resigned) the game
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\main.py:160, in _play_game_ai..run_bot_iteration(iteration)
158 # In on_step various errors can occur - log properly
159 try:
--> 160 await ai.on_step(iteration)
161 except (AttributeError,) as e:
162 logger.exception(f"Caught exception: {e}")
Cell In[32], line 72, in WorkerRushBot.on_step(self, iteration)
70 elif not self.structures(UnitTypeId.GATEWAY):
71 if self.can_afford(UnitTypeId.GATEWAY):
---> 72 await self.build(UnitTypeId.GATEWAY, near=self.structures(UnitTypeId.PYLON).closest_to(nexus))
74 # 🟡 Cybernetic Core(控制核心)
75 elif not self.structures(UnitTypeId.CYBERNETICSCORE):
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\bot_ai.py:970, in BotAI.build(self, building, near, max_distance, build_worker, random_alternative, placement_step)
968 if position is None:
969 return False
--> 970 builder = build_worker or self.select_build_worker(near)
971 if builder is None:
972 return False
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\bot_ai.py:616, in BotAI.select_build_worker(self, pos, force)
602 def select_build_worker(self, pos: Unit | Point2, force: bool = False) -> Unit | None:
603 """Select a worker to build a building with.
604
605 Example::
(...)
613 :param pos:
614 :param force:"""
615 workers = (
--> 616 self.workers.filter(lambda w: (w.is_gathering or w.is_idle) and w.distance_to(pos) < 20) or self.workers
617 )
618 if workers:
619 for worker in workers.sorted_by_distance_to(pos).prefer_idle:
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\units.py:486, in Units.filter(self, pred)
466 """Filters the current Units object and returns a new Units object.
467
468 Example::
(...)
483 :param pred:
484 """
485 assert callable(pred), "Function is not callable"
--> 486 return self.subgroup(filter(pred, self))
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\units.py:463, in Units.subgroup(self, units)
458 def subgroup(self, units: Iterable[Unit]) -> Units:
459 """Creates a new mutable Units object from Units or list object.
460
461 :param units:
462 """
--> 463 return Units(units, self._bot_object)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\units.py:29, in Units.init(self, units, bot_object)
24 def init(self, units: Iterable[Unit], bot_object: BotAI) -> None:
25 """
26 :param units:
27 :param bot_object:
28 """
---> 29 super().init(units)
30 self._bot_object = bot_object
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\bot_ai.py:616, in BotAI.select_build_worker..(w)
602 def select_build_worker(self, pos: Unit | Point2, force: bool = False) -> Unit | None:
603 """Select a worker to build a building with.
604
605 Example::
(...)
613 :param pos:
614 :param force:"""
615 workers = (
--> 616 self.workers.filter(lambda w: (w.is_gathering or w.is_idle) and w.distance_to(pos) < 20) or self.workers
617 )
618 if workers:
619 for worker in workers.sorted_by_distance_to(pos).prefer_idle:
File ~\miniconda3\envs\Starcraft\lib\functools.py:981, in cached_property.get(self, instance, owner)
979 val = cache.get(self.attrname, _NOT_FOUND)
980 if val is _NOT_FOUND:
--> 981 val = self.func(instance)
982 try:
983 cache[self.attrname] = val
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:1078, in Unit.is_gathering(self)
1074 @cached_property
1075 def is_gathering(self) -> bool:
1076 """Checks if a unit is on its way to a mineral field or vespene geyser to mine.
1077 Only works for own units."""
-> 1078 return self.is_using_ability(IS_GATHERING)
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:1050, in Unit.is_using_ability(self, abilities)
1047 def is_using_ability(self, abilities: AbilityId | set[AbilityId]) -> bool:
1048 """Check if the unit is using one of the given abilities.
1049 Only works for own units."""
-> 1050 if not self.orders:
1051 return False
1052 if isinstance(abilities, AbilityId):
File ~\miniconda3\envs\Starcraft\lib\functools.py:981, in cached_property.get(self, instance, owner)
979 val = cache.get(self.attrname, _NOT_FOUND)
980 if val is _NOT_FOUND:
--> 981 val = self.func(instance)
982 try:
983 cache[self.attrname] = val
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:1029, in Unit.orders(self)
1026 """Returns the a list of the current orders."""
1027 # TODO: add examples on how to use unit orders
1028 # pyrefly: ignore
-> 1029 return [UnitOrder.from_proto(order, self._bot_object) for order in self._proto.orders]
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:1029, in (.0)
1026 """Returns the a list of the current orders."""
1027 # TODO: add examples on how to use unit orders
1028 # pyrefly: ignore
-> 1029 return [UnitOrder.from_proto(order, self._bot_object) for order in self._proto.orders]
File ~\miniconda3\envs\Starcraft\lib\site-packages\sc2\unit.py:95, in UnitOrder.from_proto(cls, proto, bot_object)
92 elif proto.HasField("target_unit_tag"):
93 target = proto.target_unit_tag
94 return cls(
---> 95 ability=bot_object.game_data.abilities[proto.ability_id],
96 target=target,
97 progress=proto.progress,
98 )
KeyError: 4444