55
66import sys
77import os
8- sys .path .append (os .getenv ('OPENRA_PATH' , '/Users/liyao/Code/mofa/OpenCodeAlert/Copilot/openra_ai' ))
8+
9+ # 添加 OpenRA 库路径
10+ openra_path = os .getenv ('OPENRA_PATH' , '/Users/liyao/Code/mofa/OpenCodeAlert/Copilot/openra_ai' )
11+ if openra_path not in sys .path :
12+ sys .path .append (openra_path )
13+
14+ # 添加 MCP 项目中的 OpenRA_Copilot_Library 路径
15+ library_path = os .getenv ('OPENRA_LIBRARY_PATH' , '/Users/liyao/Code/mofa/Hackathon2025/examples/mcp' )
16+ if library_path not in sys .path :
17+ sys .path .append (library_path )
918
1019from OpenRA_Copilot_Library import GameAPI
1120from OpenRA_Copilot_Library .models import Location , TargetsQueryParam , Actor , MapQueryResult
@@ -86,10 +95,27 @@ def visible_units(self, type: List[str], faction: str, range: str, restrain: Lis
8695 for u in units
8796 ]
8897
89- def produce (self , unit_type : str , quantity : int ) -> int :
90- """生产指定类型和数量的单位,返回生产任务 ID"""
91- wait_id = self .api .produce (unit_type , quantity , auto_place_building = True )
92- return wait_id or - 1
98+ def produce (self , unit_type : str , quantity : int ) -> Dict [str , Any ]:
99+ """生产指定类型和数量的单位,返回详细结果"""
100+ try :
101+ wait_id = self .api .produce (unit_type , quantity , auto_place_building = True )
102+ if wait_id is None :
103+ return {
104+ "success" : False ,
105+ "error" : "生产失败 - 可能缺少必要的建筑、资源不足、或需要先展开基地车" ,
106+ "wait_id" : None
107+ }
108+ return {
109+ "success" : True ,
110+ "message" : f"成功开始生产{ unit_type } ,数量{ quantity } " ,
111+ "wait_id" : wait_id
112+ }
113+ except Exception as e :
114+ return {
115+ "success" : False ,
116+ "error" : f"生产异常: { str (e )} " ,
117+ "wait_id" : None
118+ }
93119
94120 def move_units (self , actor_ids : List [int ], x : int , y : int , attack_move : bool = False ) -> str :
95121 """移动一批单位到指定坐标"""
@@ -205,19 +231,22 @@ def update_actor(self, actor_id: int) -> Optional[Dict[str, Any]]:
205231 "hpPercent" : getattr (actor , "hp_percent" , None )
206232 }
207233
208- def deploy_units (self , actor_ids : List [int ] = None ) -> str :
234+ def deploy_units (self , actor_ids : List [int ] = None ) -> Dict [ str , Any ] :
209235 """展开或部署指定单位列表,如果没有指定ID则尝试寻找和部署基地车"""
210236 if actor_ids :
211237 # 指定了ID,正常部署
212- actors = [Actor (i ) for i in actor_ids ]
213- self .api .deploy_units (actors )
214- return "ok"
238+ try :
239+ actors = [Actor (i ) for i in actor_ids ]
240+ self .api .deploy_units (actors )
241+ return {"success" : True , "message" : f"成功部署单位ID: { actor_ids } " }
242+ except Exception as e :
243+ return {"success" : False , "error" : f"部署指定单位失败: { str (e )} " }
215244 else :
216245 # 没有指定ID,尝试直接使用 API 调用部署基地车
217246 # 1. 先尝试使用内置的 deploy_mcv_and_wait 方法
218247 try :
219248 self .api .deploy_mcv_and_wait (1.0 )
220- return "成功部署基地车 (使用内置方法)"
249+ return { "success" : True , "message" : "基地车成功展开 (使用内置方法)"}
221250 except Exception as e :
222251 print (f"内置方法失败: { e } " )
223252
@@ -233,7 +262,7 @@ def deploy_units(self, actor_ids: List[int] = None) -> str:
233262 for i , params in enumerate (deploy_attempts ):
234263 try :
235264 response = self .api ._send_request ('deploy' , params )
236- return f"成功部署 (尝试 { i + 1 } ): { response .get ('response' , '' )} "
265+ return { "success" : True , "message" : f"基地车部署成功 (方法 { i + 1 } ): { response .get ('response' , '' )} "}
237266 except Exception as e :
238267 continue
239268
@@ -243,11 +272,11 @@ def deploy_units(self, actor_ids: List[int] = None) -> str:
243272 actor = self .api .get_actor_by_id (actor_id )
244273 if actor and ('mcv' in actor .type .lower () or 'construction' in actor .type .lower () or '基地车' in actor .type ):
245274 self .api .deploy_units ([actor ])
246- return f"找到并部署基地车 ID: { actor_id } "
275+ return { "success" : True , "message" : f"找到并成功部署基地车 ID: { actor_id } "}
247276 except :
248277 continue
249278
250- return "未找到基地车可以部署,所有尝试都失败了"
279+ return { "success" : False , "error" : "未找到基地车或所有部署方法都失败了,可能需要在OpenRA游戏中手动操作或检查游戏状态" }
251280
252281 def move_camera_to_actor (self , actor_id : int ) -> str :
253282 """将镜头移动到指定 Actor 的位置"""
@@ -385,4 +414,28 @@ def place_building(self, queue_type: str, x: int = None, y: int = None) -> str:
385414 response = self .api ._send_request ('place_building' , params )
386415 return response .get ('response' , '建筑放置完成' )
387416 except Exception as e :
388- return f"放置建筑失败: { e } "
417+ return f"放置建筑失败: { e } "
418+
419+ def get_unexplored_nearby_positions (self , map_result : Dict [str , Any ], current_x : int , current_y : int , max_distance : int ) -> List [Dict [str , int ]]:
420+ """获取当前位置附近尚未探索的坐标列表"""
421+ # 将 dict 转回 MapQueryResult
422+ mq = MapQueryResult (
423+ MapWidth = map_result ["width" ],
424+ MapHeight = map_result ["height" ],
425+ Height = map_result ["heightMap" ],
426+ IsVisible = map_result ["visible" ],
427+ IsExplored = map_result ["explored" ],
428+ Terrain = map_result ["terrain" ],
429+ ResourcesType = map_result ["resourcesType" ],
430+ Resources = map_result ["resources" ]
431+ )
432+
433+ # 调用底层方法
434+ locs = self .api .get_unexplored_nearby_positions (
435+ mq ,
436+ Location (current_x , current_y ),
437+ max_distance
438+ )
439+
440+ # 序列化为 JSON-friendly 格式
441+ return [{"x" : loc .x , "y" : loc .y } for loc in locs ]
0 commit comments