diff --git a/CTF/backend/server.py b/CTF/backend/server.py index f7d2d96..7439115 100644 --- a/CTF/backend/server.py +++ b/CTF/backend/server.py @@ -1,16 +1,15 @@ import asyncio -import random from lib.game_engine import GameMap, run_game_server import threading import collections -# 1. Initialize the global world model -world = GameMap(show_gap_in_msec=10.0) +world = GameMap(show_gap_in_msec=1.0) lock = threading.Lock() last_updated_time = -1 -update_threshold = 10 +update_threshold = 1 player_to_flag_assign = {} my_side_is_left = None + class Map: def __init__(self): self.width = world.width @@ -23,6 +22,7 @@ class Map: return y * self.width + x def update(self,posx,posy): + global my_side_is_left self.width = world.width self.height = world.height self.edge = [[] for _ in range(self.width * self.height)] @@ -32,7 +32,10 @@ class Map: x, y = wall idx = self.convert_pos_to_index(x, y) self.grid[idx] = 1 - self.in_safe_zone = world.is_on_left((posx,posy)) == my_side_is_left + if my_side_is_left: + self.in_safe_zone = world.is_on_left((posx+1,posy)) == my_side_is_left + else: + self.in_safe_zone = world.is_on_left((posx-1,posy)) == my_side_is_left enemy_players = world.list_players(mine=False, inPrison=False, hasFlag=None) ally_players = world.list_players(mine=True, inPrison=False, hasFlag=None) my_pos = self.convert_pos_to_index(posx, posy) @@ -43,10 +46,18 @@ class Map: for enemy in enemy_players: x, y = enemy["posX"], enemy["posY"] idx = self.convert_pos_to_index(x, y) - self.grid[idx] = 2 - for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: - nx, ny = x + dx, y + dy - self.grid[self.convert_pos_to_index(nx,ny)] = 2 + if my_side_is_left: + if not world.is_on_left((x+1,y)): + self.grid[idx] = 2 + for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: + nx, ny = x + dx, y + dy + self.grid[self.convert_pos_to_index(nx,ny)] = 2 + else: + if world.is_on_left((x-1,y)): + self.grid[idx] = 2 + for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: + nx, ny = x + dx, y + dy + self.grid[self.convert_pos_to_index(nx,ny)] = 2 for y in range(self.height): for x in range(self.width): idx = self.convert_pos_to_index(x, y) @@ -61,10 +72,10 @@ class Map: if 0 <= nx < self.width and 0 <= ny < self.height: n_idx = self.convert_pos_to_index(nx, ny) if self.in_safe_zone: - if self.grid[n_idx] not in (1, 2): + if self.grid[n_idx] not in (1, ): self.edge[idx].append(n_idx) else: - if self.grid[n_idx] not in (1,): + if self.grid[n_idx] not in (1, 2): self.edge[idx].append(n_idx) def guideance(self, posx_start, posy_start, posx_end, posy_end): self.update(posx_start,posy_start) @@ -84,11 +95,8 @@ class Map: dist[v] = dist[u] + 1 prev[v] = u queue.append(v) - - # ---- 若不可达,返回空字符串 ---- if dist[dst_idx] == float('inf'): return "" - # ---- 重建路径(逆序) ---- path = [] cur = dst_idx while cur is not None: @@ -125,7 +133,30 @@ class Map: if dist[dst_idx] == float('inf'): return -1 return dist[dst_idx] - + def closest(self, posx_start, posy_start, positions): + closest_pos = None + min_length = float('inf') + for pos in positions: + temp = self.length(posx_start, posy_start, pos[0], pos[1]) + if temp != -1 and temp < min_length: + min_length = temp + closest_pos = pos + return closest_pos + def closest_in_range(self, posx_start, posy_start, positions): + closest_pos = None + min_length = float('inf') + for pos in positions: + if my_side_is_left: + if pos[0] >= self.width // 2: + continue + else: + if pos[0] < self.width // 2: + continue + temp = self.length(posx_start, posy_start, pos[0], pos[1]) + if temp != -1 and temp < min_length: + min_length = temp + closest_pos = pos + return closest_pos,min_length myMap = Map() def start_game(req): global player_to_flag_assign,my_side_is_left @@ -141,15 +172,27 @@ def plan_next_actions(req): global player_to_flag_assign,myMap,my_side_is_left my_players = world.list_players(mine=True, inPrison=False, hasFlag=None) - opponents = world.list_players(mine=False, inPrison=False, hasFlag=None) + enemy_players_flags = world.list_players(mine=False, inPrison=False, hasFlag=True) + enemy_players = world.list_players(mine=False, inPrison=False, hasFlag=False) enemy_flags = world.list_flags(mine=False, canPickup=True) - + my_flags = world.list_flags(mine=True, canPickup=True) my_targets = list(world.list_targets(mine=True)) - active_player_names = {p["name"] for p in my_players if not p["hasFlag"]} flags_list = [] - for flags in opponents: + regard_list = [] + pretend_list = [] + protect_list = [] + targets_list = [] + for flags in enemy_flags: flags_list.append((flags["posX"],flags["posY"])) + for p in enemy_players_flags: + regard_list.append((p["posX"],p["posY"])) + for p in enemy_players: + pretend_list.append((p["posX"],p["posY"])) + for flags in my_flags: + protect_list.append((flags["posX"],flags["posY"])) + for t in my_targets: + targets_list.append((t[0],t[1])) player_to_flag_assign = { name: pos for name, pos in player_to_flag_assign.items() if name in active_player_names @@ -158,37 +201,46 @@ def plan_next_actions(req): for p in my_players: if p["name"] not in active_player_names: continue - if p["name"] in player_to_flag_assign and player_to_flag_assign[p["name"]] != None and player_to_flag_assign[p["name"]] in flags_list: + if p["name"] in player_to_flag_assign and player_to_flag_assign[p["name"]] in flags_list: + flags_list.remove(player_to_flag_assign[p["name"]]) continue - closest_flag = None - min_length = float('inf') - for f in enemy_flags: - temp = myMap.length(p["posX"],p["posY"],f["posX"],f["posY"]) - if temp != -1 and temp < min_length: - min_length = temp - closest_flag = f - f = closest_flag if closest_flag is not None else random.choice(enemy_flags) - player_to_flag_assign[p["name"]] = (f["posX"], f["posY"]) + f = myMap.closest(p["posX"],p["posY"],flags_list) + if f is not None: + player_to_flag_assign[p["name"]] = (f[0],f[1]) + flags_list.remove((f[0],f[1])) - # 3. Plan moves for each player player_moves = {} for p in my_players: - curr_pos = (p["posX"], p["posY"]) - - # Determine Target: Either the assigned flag or the home target if p["hasFlag"]: - dest = my_targets[0] + dest,temp = myMap.closest_in_range(p["posX"],p["posY"],my_targets) + f,lentime = myMap.closest_in_range(p["posX"],p["posY"],regard_list) + if (f is not None) and (lentime<=5): + dest = (f[0],f[1]) elif p["name"] in player_to_flag_assign: dest = player_to_flag_assign[p["name"]] + f,lentime = myMap.closest_in_range(p["posX"],p["posY"],regard_list) + if f is not None and lentime<=10: + dest = (f[0],f[1]) + else : + f,lentime = myMap.closest_in_range(p["posX"],p["posY"],pretend_list) + if f is not None and lentime<8: + dest = (f[0],f[1]) else: - continue - - # Determine Obstacles: Avoid opponents if we are in enemy territory - is_safe = world.is_on_left(curr_pos) == my_side_is_left - + f,temp = myMap.closest_in_range(p["posX"],p["posY"],regard_list) + if f is not None: + dest = (f[0],f[1]) + else: + f = myMap.closest(p["posX"],p["posY"],pretend_list) + if f is not None: + dest = (f[0],f[1]) + else: + f= myMap.closest(p["posX"],p["posY"],protect_list) + if f is not None: + dest = (f[0],f[1]) + else: + continue player_moves[p["name"]] = myMap.guideance(p["posX"],p["posY"],dest[0],dest[1]) - return player_moves def game_over(req):