diff --git a/obsazovani.md b/obsazovani.md index 39eb3dc..eb10529 100644 --- a/obsazovani.md +++ b/obsazovani.md @@ -106,7 +106,11 @@ Metadata # S možnou změnou initial_remaining_rounds: - born_per_round: # pro každý tah počet, pokud je kratší, uvažujeme cyklicky + # Parametry k počtu nových vojáků + # Pomyslná cena *nového* vojáka + spawn_price: + # Na kolik nových spawnů bude stačit obnos "peněz" v posledním kole + last_spawn: } ``` diff --git a/server/hra/game.py b/server/hra/game.py index 6ba4af1..73664bd 100644 --- a/server/hra/game.py +++ b/server/hra/game.py @@ -33,6 +33,12 @@ class Occupy(Logic): "up": (-1, 0), "down": (1, 0) } + # Jaké území okolo domečku je chráněné + PROTECTED_AREA = [ + [-1, -1], [-1, 0], [-1, 1], + [0, -1], [0, 0], [0, 1], + [1, -1], [1, 0], [1, 1] + ] def __init__(self, teams_count: int, configuration: Any): super().__init__(teams_count, configuration) @@ -41,8 +47,10 @@ class Occupy(Logic): assert(teams_count == self.teams_width * self.teams_height) self.map_width = self.teams_width * configuration["width_per_team"] self.map_height = self.teams_height * configuration["height_per_team"] - # born per round - nultý index je počet vojáků každého týmu v zero-stavu - self.bpr = self.configuration["born_per_round"] + # Parametry k počtu nových vojáků + self.rounds_total = configuration["initial_remaining_rounds"] + self.spawn_price = configuration["spawn_price"] + self.last_spawn = configuration["last_spawn"] def generate_soldier(self, team_id, soldier_id): return { @@ -51,6 +59,9 @@ class Occupy(Logic): "id": soldier_id, "remaining_rounds": 1 } + + def budget_for_round(self, round_id): + return (self.last_spawn * self.spawn_price * (round_id + 1)**2) // (self.rounds_total**2) # Počáteční stav def zero_state(self) -> Any: @@ -77,7 +88,7 @@ class Occupy(Logic): map[home_y][home_x]["home_for_team"] = team_id map[home_y][home_x]["occupied_by_team"] = team_id # Initial stav vojáků: - for soldier_id in range(self.bpr[0]): + for soldier_id in range(max(1, self.budget_for_round(0) // self.spawn_price)): map[home_y][home_x]["members"].append(self.generate_soldier(team_id, soldier_id)) team_id += 1 home_x += self.configuration["width_per_team"] @@ -115,12 +126,19 @@ class Occupy(Logic): home_positions = [None] * self.teams_count # 2D array s `True`s tam, kde je hill hills = [[False] * self.map_width for _ in range(self.map_height)] + # 2D array s ID týmu, který zde má chráněné území (okolo domečku) + # (-1 tam, kde nikdo nemá domeček) + protected_for = [[-1] * self.map_width for _ in range(self.map_height)] y = 0 for row in state["map"]: x = 0 for field in row: hills[y][x] = field["hill"] + hft = field["home_for_team"] + if hft is not None: + for p in self.PROTECTED_AREA: + protected_for[(y + p[0]) % self.map_height][(x + p[1]) % self.map_width] = hft if field["home_for_team"] is not None: home_positions[field["home_for_team"]] = [y, x] for member in field["members"]: @@ -151,8 +169,9 @@ class Occupy(Logic): orig_x = id_positions[team_id][soldier_id][1] new_y = (orig_y + move_vect[0]) % self.map_height new_x = (orig_x + move_vect[1]) % self.map_width - if hills[new_y][new_x]: - # Voják se snažil lézt na skálu, zůstane na původním místě + # Chráněné území nebo skála + if (protected_for[new_y][new_x] > -1 and protected_for[new_y][new_x] != team_id) \ + or hills[new_y][new_x]: soldier_lists[orig_y][orig_x][team_id].append(soldier_id) else: soldier_lists[new_y][new_x][team_id].append(soldier_id) @@ -160,7 +179,9 @@ class Occupy(Logic): # Přidáme vojáky v homes: for team_id in range(self.teams_count): home_pos = home_positions[team_id] - for i in range(self.bpr[(round_id + 1) % len(self.bpr)]): + soldier_count = len(all_ids[team_id]) + spawn_count = max(1, (self.budget_for_round(round_id) - soldier_count) // self.spawn_price) + for i in range(spawn_count): soldier_lists[home_pos[0]][home_pos[1]][team_id].append(highest_ids[team_id] + i + 1) # Vojáci se pomlátí: @@ -169,7 +190,12 @@ class Occupy(Logic): team_strengths = [len(soldier_lists[y][x][tid]) for tid in range(self.teams_count)] team_strengths.sort() for tid in range(self.teams_count): - soldier_lists[y][x][tid] = soldier_lists[y][x][tid][team_strengths[-2]:] + soldier_count = len(soldier_lists[y][x][tid]) + if soldier_count <= team_strengths[-2]: + soldier_lists[y][x][tid] = [] + else: + remaining_count = soldier_count - (team_strengths[-2]**2 // soldier_count) + soldier_lists[y][x][tid] = soldier_lists[y][x][tid][0:remaining_count] # Vygenerujeme výsledek: score = [0] * self.teams_count @@ -212,6 +238,8 @@ class Occupy(Logic): id_positions = {} # 2D array s `True`s tam, kde je hill hills = [[False] * self.map_width for _ in range(self.map_height)] + # 2D array `True` na chráněných územích ostatních týmů + protected = [[False] * self.map_width for _ in range(self.map_height)] # ID soldierů, se kterými tým už hnul ids_moved = {} @@ -220,6 +248,9 @@ class Occupy(Logic): x = 0 for field in row: hills[y][x] = field["hill"] + if field["home_for_team"] is not None and field["home_for_team"] != team_id: + for p in self.PROTECTED_AREA: + protected[(y + p[0]) % self.map_height][(x + p[1]) % self.map_width] = True for member in field["members"]: if member["team"] != team_id: continue @@ -240,7 +271,9 @@ class Occupy(Logic): move_vect = self.MOVE_VECTORS[member["action"]] new_position_y = (id_positions[member["id"]][0] + move_vect[0]) % self.map_height new_position_x = (id_positions[member["id"]][1] + move_vect[1]) % self.map_width - if hills[new_position_y][new_position_x]: + if protected[new_position_y][new_position_x]: + warns.append(self.generate_warn(member["id"], "Voják se snaží dostat do domečku cizího týmu. To není povoleno.")) + elif hills[new_position_y][new_position_x]: warns.append(self.generate_warn(member["id"], "Voják se snaží vylézt na skálu, což nejde.")) if len(warns) == 0: