Browse Source

Strategická: úpravy logiky

Ochrana domečků, nová úmrtnost při bitvách, spawnování závislé na aktuálním počtu vojáků
master
Martin Koreček 2 years ago
parent
commit
748a640b83
  1. 6
      obsazovani.md
  2. 49
      server/hra/game.py

6
obsazovani.md

@ -106,7 +106,11 @@ Metadata
# S možnou změnou # S možnou změnou
initial_remaining_rounds: <int> initial_remaining_rounds: <int>
born_per_round: <List[int]> # 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: <int>
# Na kolik nových spawnů bude stačit obnos "peněz" v posledním kole
last_spawn: <int>
} }
``` ```

49
server/hra/game.py

@ -33,6 +33,12 @@ class Occupy(Logic):
"up": (-1, 0), "up": (-1, 0),
"down": (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): def __init__(self, teams_count: int, configuration: Any):
super().__init__(teams_count, configuration) super().__init__(teams_count, configuration)
@ -41,8 +47,10 @@ class Occupy(Logic):
assert(teams_count == self.teams_width * self.teams_height) assert(teams_count == self.teams_width * self.teams_height)
self.map_width = self.teams_width * configuration["width_per_team"] self.map_width = self.teams_width * configuration["width_per_team"]
self.map_height = self.teams_height * configuration["height_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 # Parametry k počtu nových vojáků
self.bpr = self.configuration["born_per_round"] 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): def generate_soldier(self, team_id, soldier_id):
return { return {
@ -51,6 +59,9 @@ class Occupy(Logic):
"id": soldier_id, "id": soldier_id,
"remaining_rounds": 1 "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 # Počáteční stav
def zero_state(self) -> Any: 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]["home_for_team"] = team_id
map[home_y][home_x]["occupied_by_team"] = team_id map[home_y][home_x]["occupied_by_team"] = team_id
# Initial stav vojáků: # 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)) map[home_y][home_x]["members"].append(self.generate_soldier(team_id, soldier_id))
team_id += 1 team_id += 1
home_x += self.configuration["width_per_team"] home_x += self.configuration["width_per_team"]
@ -115,12 +126,19 @@ class Occupy(Logic):
home_positions = [None] * self.teams_count home_positions = [None] * self.teams_count
# 2D array s `True`s tam, kde je hill # 2D array s `True`s tam, kde je hill
hills = [[False] * self.map_width for _ in range(self.map_height)] 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 y = 0
for row in state["map"]: for row in state["map"]:
x = 0 x = 0
for field in row: for field in row:
hills[y][x] = field["hill"] 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: if field["home_for_team"] is not None:
home_positions[field["home_for_team"]] = [y, x] home_positions[field["home_for_team"]] = [y, x]
for member in field["members"]: for member in field["members"]:
@ -151,8 +169,9 @@ class Occupy(Logic):
orig_x = id_positions[team_id][soldier_id][1] orig_x = id_positions[team_id][soldier_id][1]
new_y = (orig_y + move_vect[0]) % self.map_height new_y = (orig_y + move_vect[0]) % self.map_height
new_x = (orig_x + move_vect[1]) % self.map_width new_x = (orig_x + move_vect[1]) % self.map_width
if hills[new_y][new_x]: # Chráněné území nebo skála
# Voják se snažil lézt na skálu, zůstane na původním místě 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) soldier_lists[orig_y][orig_x][team_id].append(soldier_id)
else: else:
soldier_lists[new_y][new_x][team_id].append(soldier_id) 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: # Přidáme vojáky v homes:
for team_id in range(self.teams_count): for team_id in range(self.teams_count):
home_pos = home_positions[team_id] 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) soldier_lists[home_pos[0]][home_pos[1]][team_id].append(highest_ids[team_id] + i + 1)
# Vojáci se pomlátí: # 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 = [len(soldier_lists[y][x][tid]) for tid in range(self.teams_count)]
team_strengths.sort() team_strengths.sort()
for tid in range(self.teams_count): 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: # Vygenerujeme výsledek:
score = [0] * self.teams_count score = [0] * self.teams_count
@ -212,6 +238,8 @@ class Occupy(Logic):
id_positions = {} id_positions = {}
# 2D array s `True`s tam, kde je hill # 2D array s `True`s tam, kde je hill
hills = [[False] * self.map_width for _ in range(self.map_height)] 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 # ID soldierů, se kterými tým už hnul
ids_moved = {} ids_moved = {}
@ -220,6 +248,9 @@ class Occupy(Logic):
x = 0 x = 0
for field in row: for field in row:
hills[y][x] = field["hill"] 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"]: for member in field["members"]:
if member["team"] != team_id: if member["team"] != team_id:
continue continue
@ -240,7 +271,9 @@ class Occupy(Logic):
move_vect = self.MOVE_VECTORS[member["action"]] move_vect = self.MOVE_VECTORS[member["action"]]
new_position_y = (id_positions[member["id"]][0] + move_vect[0]) % self.map_height 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 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.")) warns.append(self.generate_warn(member["id"], "Voják se snaží vylézt na skálu, což nejde."))
if len(warns) == 0: if len(warns) == 0:

Loading…
Cancel
Save