From 6f79459d83b3bd5b77f89bda0ec293dfb5a9be3c Mon Sep 17 00:00:00 2001 From: jxd136 Date: Mon, 1 Jun 2026 21:48:42 +0800 Subject: [PATCH 1/2] fix: fix --- .../Debug/net8.0/installer.AssemblyInfo.cs | 2 +- .../net8.0/installer.AssemblyInfoInputs.cache | 2 +- logic/pve/official_evaluator.py | 20 +- logic/pve/submission/agent.py | 2201 +++++++---------- logic/pve/submission/model.pt | Bin 232 -> 1249 bytes .../tests/test_official_evaluator_rules.py | 2 + models/test/ppo_thuai9_best.zip | Bin 0 -> 277955 bytes .../obj/Debug/net8.0/playback.AssemblyInfo.cs | 2 +- .../net8.0/playback.AssemblyInfoInputs.cache | 2 +- 9 files changed, 893 insertions(+), 1338 deletions(-) create mode 100644 models/test/ppo_thuai9_best.zip diff --git a/installer/installer/obj/Debug/net8.0/installer.AssemblyInfo.cs b/installer/installer/obj/Debug/net8.0/installer.AssemblyInfo.cs index 9ca16e88..db639d9d 100644 --- a/installer/installer/obj/Debug/net8.0/installer.AssemblyInfo.cs +++ b/installer/installer/obj/Debug/net8.0/installer.AssemblyInfo.cs @@ -13,7 +13,7 @@ [assembly: System.Reflection.AssemblyCompanyAttribute("installer")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+9f7db73aae63536d35e02c009a73a2d19a4a6e8d")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6c55dad574f4c42903af5b9996d72a8b23b25485")] [assembly: System.Reflection.AssemblyProductAttribute("installer")] [assembly: System.Reflection.AssemblyTitleAttribute("installer")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/installer/installer/obj/Debug/net8.0/installer.AssemblyInfoInputs.cache b/installer/installer/obj/Debug/net8.0/installer.AssemblyInfoInputs.cache index d914c91c..968e0eeb 100644 --- a/installer/installer/obj/Debug/net8.0/installer.AssemblyInfoInputs.cache +++ b/installer/installer/obj/Debug/net8.0/installer.AssemblyInfoInputs.cache @@ -1 +1 @@ -1b88c640623d488f80a81c10471e8c7d1e02a9c981c51eac3c8033d039a1e22f +7bb77af3ee0abd80638d125c2539832beada777088237eb6eb5bb82c51a91208 diff --git a/logic/pve/official_evaluator.py b/logic/pve/official_evaluator.py index 63a6d0f1..904526a6 100644 --- a/logic/pve/official_evaluator.py +++ b/logic/pve/official_evaluator.py @@ -52,6 +52,10 @@ "RLInterfaces", "RLInterfaces.base_agent", } +_ALLOWED_GAMELOGIC_IMPORTS = { + "Action", + "N_ACTIONS", +} class SubmissionRuleError(RuntimeError): @@ -82,8 +86,15 @@ def _error(self, node: ast.AST, message: str) -> None: def visit_ImportFrom(self, node: ast.ImportFrom) -> None: module = node.module or "" - if module.startswith("GameLogic"): - self._error(node, "imports from GameLogic are not allowed in submissions") + if module == "GameLogic": + for alias in node.names: + if alias.name not in _ALLOWED_GAMELOGIC_IMPORTS: + self._error( + node, + "only Action and N_ACTIONS may be imported from GameLogic by submissions", + ) + elif module.startswith("GameLogic"): + self._error(node, "imports from GameLogic internal modules are not allowed in submissions") if module.startswith("RLInterfaces") and module not in _ALLOWED_RL_IMPORTS: self._error( node, @@ -101,7 +112,10 @@ def visit_ImportFrom(self, node: ast.ImportFrom) -> None: def visit_Import(self, node: ast.Import) -> None: for alias in node.names: if alias.name == "GameLogic" or alias.name.startswith("GameLogic."): - self._error(node, "imports from GameLogic are not allowed in submissions") + self._error( + node, + "use 'from GameLogic import Action, N_ACTIONS' instead of importing GameLogic modules", + ) if alias.name == "RLInterfaces" or ( alias.name.startswith("RLInterfaces.") and alias.name not in _ALLOWED_RL_IMPORTS ): diff --git a/logic/pve/submission/agent.py b/logic/pve/submission/agent.py index 0ccb63c7..83cacbd7 100644 --- a/logic/pve/submission/agent.py +++ b/logic/pve/submission/agent.py @@ -1,1392 +1,931 @@ +""" +THUAI9 PvE-RL Agent — 纯套利策略(v7)。 + +核心策略: +1. 开局抢占算力中心 → 累积 compute +2. 获取 TECH_1 + TECH_5(消除移动冷却)+ TECH_3(容量+50%) +3. 跨市场套利为主要(唯一)利润来源 +4. 不采集不生产——在 volatility=2.0 下套利效率远超生产 +5. A* 路径缓存 + 买入来源追踪 +""" from __future__ import annotations -import json +import os import math import random -import tempfile -import zipfile -from pathlib import Path -from typing import Any +import heapq +from collections import deque +from typing import Any, Dict, List, Optional, Tuple import numpy as np +import torch +import torch.nn as nn +from GameLogic import N_ACTIONS from RLInterfaces import BaseAgent -WAIT = 0 -MOVE_UP = 1 -MOVE_DOWN = 2 -MOVE_LEFT = 3 -MOVE_RIGHT = 4 -BUY = 5 -SELL_0 = 6 -SELL_4 = 10 -HARVEST = 11 -DEPOSIT = 12 -PRODUCE_0 = 13 -PRODUCE_4 = 17 -LOAD = 18 -OCCUPY = 19 -TECH_0 = 20 -TECH_7 = 27 - -N_PRIMITIVE_ACTIONS = 28 -OBS_DIM = 82 - -FOLLOW_EXPERT = 0 -BUY_MARKET_0 = 1 -BUY_MARKET_3 = 4 -SELL_MARKET_0 = 5 -SELL_MARKET_3 = 8 -FACTORY_PLAN = 9 -OCCUPY_NEAREST = 10 -WAIT_FOR_PRICE = 11 -ENDGAME_LIQUIDATE = 12 -MACRO_ACTION_COUNT = 13 -MACRO_OBS_DIM = 168 -BUNDLE_FORMAT = "thuai9-new-rules-router" - -DIFFICULTIES = ("easy", "medium", "hard") -MAP_SIZE = {"easy": 5, "medium": 10, "hard": 15} -MARKET_COUNT = {"easy": 3, "medium": 3, "hard": 4} -CAPACITY_BASE = {"easy": 30.0, "medium": 30.0, "hard": 30.0} - -PRICE_LO = np.asarray([40.0, 20.0, 4.0, 32.0, 12.0], dtype=np.float32) -PRICE_RANGE = np.asarray([80.0, 40.0, 8.0, 64.0, 12.0], dtype=np.float32) -RAW_COST = np.asarray([5.0, 3.0, 1.0, 4.0, 2.0], dtype=np.float32) -MOVE_DELTAS = { - MOVE_UP: (-1, 0), - MOVE_DOWN: (1, 0), - MOVE_LEFT: (0, -1), - MOVE_RIGHT: (0, 1), -} -SELL_ACTIONS = tuple(range(SELL_0, SELL_4 + 1)) -PRODUCE_ACTIONS = tuple(range(PRODUCE_0, PRODUCE_4 + 1)) -TECH_ACTIONS = tuple(range(TECH_0, TECH_7 + 1)) - - -class ExpertParams: - def __init__( - self, - buy_fill: float, - endgame_time: float, - wait_until_time: float, - distance_penalty: float, - sell_margin: float, - explore_after: int, - occupy_until: float, - factory_until: float, - tech_priority: tuple[int, ...], - ): - self.buy_fill = buy_fill - self.endgame_time = endgame_time - self.wait_until_time = wait_until_time - self.distance_penalty = distance_penalty - self.sell_margin = sell_margin - self.explore_after = explore_after - self.occupy_until = occupy_until - self.factory_until = factory_until - self.tech_priority = tech_priority - - -EXPERT_PARAMS = { - "easy": ExpertParams( - buy_fill=0.78, - endgame_time=0.88, - wait_until_time=0.48, - distance_penalty=10.0, - sell_margin=0.0, - explore_after=45, - occupy_until=0.20, - factory_until=0.50, - tech_priority=(23, 22, 20, 21, 25), - ), - "medium": ExpertParams( - buy_fill=0.72, - endgame_time=0.84, - wait_until_time=0.40, - distance_penalty=16.0, - sell_margin=2.0, - explore_after=65, - occupy_until=0.28, - factory_until=0.58, - tech_priority=(23, 20, 22, 21, 25), - ), - "hard": ExpertParams( - buy_fill=0.64, - endgame_time=0.78, - wait_until_time=0.34, - distance_penalty=24.0, - sell_margin=4.0, - explore_after=90, - occupy_until=0.35, - factory_until=0.66, - tech_priority=(23, 21, 25, 20, 22, 26), - ), +class PolicyNet(nn.Module): + def __init__(self, obs_dim=82, act_dim=28, hidden=512): + super().__init__() + self.net = nn.Sequential( + nn.Linear(obs_dim, hidden), nn.BatchNorm1d(hidden), nn.ReLU(inplace=True), + nn.Dropout(0.15), + nn.Linear(hidden, hidden), nn.BatchNorm1d(hidden), nn.ReLU(inplace=True), + nn.Dropout(0.15), + nn.Linear(hidden, hidden), nn.BatchNorm1d(hidden), nn.ReLU(inplace=True), + nn.Dropout(0.15), + nn.Linear(hidden, act_dim), + ) + def forward(self, obs, mask): + logits = self.net(obs) + logits[~mask] = -1e9 + return logits + + +# ── 动作常量 ────────────────────────────────────────────────────────────────── +WAIT, MOVE_UP, MOVE_DOWN, MOVE_LEFT, MOVE_RIGHT = 0, 1, 2, 3, 4 +BUY, HARVEST, DEPOSIT, LOAD, OCCUPY = 5, 11, 12, 18, 19 +SELL_0, SELL_1, SELL_2, SELL_3, SELL_4 = 6, 7, 8, 9, 10 +PRODUCE_0, PRODUCE_1, PRODUCE_2, PRODUCE_3, PRODUCE_4 = 13, 14, 15, 16, 17 +TECH_0, TECH_1, TECH_2, TECH_3, TECH_4, TECH_5, TECH_6, TECH_7 = range(20, 28) + +SELL_ACTIONS = [SELL_0, SELL_1, SELL_2, SELL_3, SELL_4] +PROD_ACTIONS = [PRODUCE_0, PRODUCE_1, PRODUCE_2, PRODUCE_3, PRODUCE_4] +TECH_ACTIONS = list(range(20, 28)) + +MOVE_DELTA = {MOVE_UP: (-1, 0), MOVE_DOWN: (1, 0), MOVE_LEFT: (0, -1), MOVE_RIGHT: (0, 1)} +MOVE_SET = {MOVE_UP, MOVE_DOWN, MOVE_LEFT, MOVE_RIGHT} + +# 科技名 → TECH_x 映射(用于按需购买) +TECH_KEY_TO_ID = { + "efficiency": TECH_1, + "path_optimization": TECH_5, + "durability": TECH_3, + "marketing": TECH_2, + "compute_expansion": TECH_7, } +# 科技购买优先级:路径优化→扩容→提价(path_opt 消除移动冷却最优先) +TECH_PRIORITY = ["efficiency", "path_optimization", "durability", "marketing"] -def _valid_indices(mask: np.ndarray) -> np.ndarray: - return np.flatnonzero(np.asarray(mask, dtype=bool)) - - -def _safe_mask(env: Any) -> np.ndarray: - try: - mask = np.asarray(env.action_masks(), dtype=bool) - if mask.shape == (N_PRIMITIVE_ACTIONS,): - return mask - except Exception: - pass - mask = np.zeros(N_PRIMITIVE_ACTIONS, dtype=bool) - mask[WAIT] = True - return mask - - -class SafetyLayer: - def __init__(self, env: Any): - self.env = env - - def mask(self) -> np.ndarray: - return _safe_mask(self.env) - - def valid_indices(self, mask: np.ndarray) -> np.ndarray: - return _valid_indices(mask) - - def ensure_valid(self, action: int, mask: np.ndarray, fallback: int = WAIT) -> int: - if 0 <= int(action) < len(mask) and bool(mask[int(action)]): - return int(action) - if 0 <= int(fallback) < len(mask) and bool(mask[int(fallback)]): - return int(fallback) - valid = self.valid_indices(mask) - return int(valid[0]) if len(valid) else WAIT - - -def money_from_obs(obs: np.ndarray) -> float: - return max(0.0, float(10 ** (float(obs[10]) * 5.0) - 1.0)) - - -def compute_from_obs(obs: np.ndarray) -> float: - return max(0.0, float(obs[11]) * 100.0) - - -def time_ratio(obs: np.ndarray) -> float: - return float(np.clip(obs[12], 0.0, 1.0)) - - -def product_inventory(obs: np.ndarray) -> float: - return float(np.sum(np.clip(obs[4:9], 0.0, 2.0))) - +PRODUCT = { + 0: {"cost": 10, "raw": 5, "lo": 40, "hi": 120, "time": 5.0}, + 1: {"cost": 5, "raw": 3, "lo": 20, "hi": 60, "time": 4.0}, + 2: {"cost": 1, "raw": 1, "lo": 4, "hi": 12, "time": 2.0}, + 3: {"cost": 8, "raw": 4, "lo": 32, "hi": 96, "time": 6.0}, + 4: {"cost": 3, "raw": 2, "lo": 12, "hi": 24, "time": 1.0}, +} -def total_inventory(obs: np.ndarray) -> float: - return float(np.clip(obs[3], 0.0, 2.0) + product_inventory(obs)) +# 观测索引 +OFF_X, OFF_Y, OFF_RAW, OFF_PROD = 0, 1, 3, 4 +OFF_BUSY, OFF_MONEY, OFF_COMP, OFF_TIME = 9, 10, 11, 12 +OFF_RES, OFF_CENTER, OFF_MARKET, OFF_TECH = 22, 34, 46, 74 +CAP = 30.0 -def tech_owned(obs: np.ndarray, tech_action: int) -> bool: - idx = int(tech_action) - TECH_0 - if 0 <= idx < 8: - return bool(float(obs[74 + idx]) > 0.5) - return False +def _price(pid, norm): + p = PRODUCT[pid] + rng = max(1.0, p["hi"] - p["lo"]) + return norm * rng + p["lo"] -def infer_difficulty(obs: np.ndarray) -> str: - money = money_from_obs(obs) - compute = compute_from_obs(obs) - if money >= 100.0 or compute >= 50.0: - return "easy" - if money <= 40.0 or compute <= 25.0: - return "hard" - return "medium" +class Agent(BaseAgent): + def __init__(self, env, mode="rule"): + super().__init__(env) + self.mode = mode + self.policy_net = None + + self.x = self.y = 0 + self.H = self.W = 0 + self._map_ok = False + + # 实体位置(obs 每步刷新) + self.mkts = {} # mid → (x, y) + self.res = {} # rid → (x, y) + self.ctrs = {} # cid → (x, y) + + # 经济 + self.money = 0.0 + self.compute = 0.0 + + # 记忆 + self._techs = set() + self._obs = set() # 已知障碍 + self._black = set() # 黑名单(不可达目标) + self._black_t = {} + self._cells = set() # 已访问 + self._fail = {} + + # 目标系统 + self._goal = None # (gx, gy) + self._goal_act = None # 到达后执行的动作 + self._goal_steps = 0 + self._goal_start_dist = 0 + self._state = "EXPLORE" + + # 卡住检测 + self._pos_hist = [] + + # Episode 检测 + self._last_t = -1.0 + self._eps_steps = 0 + + # 重规划 + self._replan = True + + # ── 新增:路径缓存 ── + self._path_cache = {} # (sx,sy,gx,gy) → [actions] or None + self._path_hits = 0 + self._path_misses = 0 + + # ── 新增:买入追踪 ── + self._last_buy_mid = None # 最近买入的市场 id + self._has_bought = False # 是否持有通过 BUY 获得的产品 + + # ── 新增:算力中心追踪 ── + self._occupied = set() # 已占领的算力中心 id + + # ── 新增:科技购买追踪(防止反复尝试)── + self._tech_attempted = {} # tech_key → fail_count + + # ═══════════════════════════════════════════════════════════════════════════ + # 观测 + # ═══════════════════════════════════════════════════════════════════════════ + + def _reset(self): + self._obs.clear() + self._black.clear() + self._black_t.clear() + self._cells.clear() + self._fail.clear() + self._pos_hist.clear() + self._techs.clear() + self._goal = None + self._goal_act = None + self._goal_steps = 0 + self._goal_start_dist = 0 + self._state = "EXPLORE" + self._replan = True + self._eps_steps = 0 + self._path_cache.clear() + self._last_buy_mid = None + self._has_bought = False + self._occupied.clear() + self._tech_attempted.clear() + + def _read_obs(self, obs): + # 地图检测 + if not self._map_ok: + m = 10 ** (obs[OFF_MONEY] * 5) - 1 + if m > 150: + self.H = self.W = 5 + elif m > 40: + self.H = self.W = 10 + else: + self.H = self.W = 15 + self._map_ok = True + + # Episode 重置检测 + t = obs[OFF_TIME] + if self._last_t >= 0 and t < self._last_t - 0.05: + self._reset() + self._last_t = t + self._eps_steps += 1 + + H, W = max(1, self.H), max(1, self.W) + + # 位置 + self.x = int(round(obs[OFF_X] * H)) + self.y = int(round(obs[OFF_Y] * W)) + + # 经济 + self.compute = obs[OFF_COMP] * 100.0 + self.money = 10 ** (obs[OFF_MONEY] * 5) - 1 + + # 资源 + self.res.clear() + for i in range(4): + b = OFF_RES + i * 3 + dx, dy = obs[b], obs[b + 1] + if abs(dx) + abs(dy) < 1e-6: + continue + rx = self.x + int(round(dx * H)) + ry = self.y + int(round(dy * W)) + if 0 <= rx < H and 0 <= ry < W: + self.res[i] = (rx, ry) + + # 中心 + self.ctrs.clear() + for i in range(3): + b = OFF_CENTER + i * 4 + dx, dy = obs[b], obs[b + 1] + if abs(dx) + abs(dy) < 1e-6: + continue + cx = self.x + int(round(dx * H)) + cy = self.y + int(round(dy * W)) + if 0 <= cx < H and 0 <= cy < W: + self.ctrs[i] = (cx, cy) + + # 市场 + self.mkts.clear() + for i in range(4): + b = OFF_MARKET + i * 7 + dx, dy = obs[b], obs[b + 1] + if abs(dx) + abs(dy) < 1e-6: + # 站在市场上:位置就是自身 + mx, my = self.x, self.y + else: + mx = self.x + int(round(dx * H)) + my = self.y + int(round(dy * W)) + if 0 <= mx < H and 0 <= my < W: + self.mkts[i] = (mx, my) + + # 检测新占领的算力中心 + self._check_new_centers(obs) + + # 更新买入追踪:如果身上没有产品了,清除标记 + if not self._has_prod(obs): + self._has_bought = False + self._last_buy_mid = None + + def _check_new_centers(self, obs): + """检测是否有新占领的算力中心。""" + for i in range(3): + b = OFF_CENTER + i * 4 + if b + 2 < len(obs) and obs[b + 2] > 0.5: + self._occupied.add(i) + + # ═══════════════════════════════════════════════════════════════════════════ + # 辅助 + # ═══════════════════════════════════════════════════════════════════════════ + + def _prices(self, obs, mid): + b = OFF_MARKET + mid * 7 + 2 + return {pid: _price(pid, obs[b + pid]) for pid in range(5)} + + def _all_prices(self, obs): + return {mid: self._prices(obs, mid) for mid in self.mkts} + + def _techs_owned(self, obs): + return [obs[OFF_TECH + i] > 0.5 for i in range(8)] + + def _busy(self, obs): + return obs[OFF_BUSY] * 10.0 > 0.5 + + def _has_raw(self, obs): + return obs[OFF_RAW] * CAP > 0.5 + + def _has_prod(self, obs): + return any(obs[OFF_PROD + i] * CAP > 0.01 for i in range(5)) + + def _raw_qty(self, obs): + return obs[OFF_RAW] * CAP + + def _prod_inv(self, obs): + return {pid: obs[OFF_PROD + pid] * CAP for pid in range(5) + if obs[OFF_PROD + pid] * CAP > 0.01} + + def _at_factory(self): + return self.x == 0 and self.y == 0 + + def _capacity(self, obs): + return 45.0 if self._techs_owned(obs)[3] else 30.0 + + # ═══════════════════════════════════════════════════════════════════════════ + # 障碍物学习 + # ═══════════════════════════════════════════════════════════════════════════ + + def _learn_obs(self, mask): + """标记被封堵的移动方向。""" + for act, (dx, dy) in MOVE_DELTA.items(): + if not mask[act]: + nx, ny = self.x + dx, self.y + dy + if 0 <= nx < self.H and 0 <= ny < self.W: + if (nx, ny) not in self._cells: + self._obs.add((nx, ny)) + + def _check_stuck(self): + self._pos_hist.append((self.x, self.y)) + if len(self._pos_hist) > 30: + self._pos_hist.pop(0) + if len(self._pos_hist) >= 25: + if len(set(self._pos_hist)) <= 3: + self._obs.clear() + self._black.clear() + self._black_t.clear() + self._pos_hist.clear() + self._path_cache.clear() + self._goal = None + self._goal_act = None + self._replan = True + + # ═══════════════════════════════════════════════════════════════════════════ + # A*(带缓存) + # ═══════════════════════════════════════════════════════════════════════════ + + def _astar(self, gx, gy): + if (self.x, self.y) == (gx, gy): + return [] + if not (0 <= gx < self.H and 0 <= gy < self.W): + return None + if (gx, gy) in self._obs: + return None -def params_for(difficulty: str) -> ExpertParams: - return EXPERT_PARAMS.get(difficulty, EXPERT_PARAMS["medium"]) + # 检查缓存 + cache_key = (self.x, self.y, gx, gy) + if cache_key in self._path_cache: + self._path_hits += 1 + return self._path_cache[cache_key] + self._path_misses += 1 -class DifficultyRouter: - def __init__(self, models: dict[str, Any] | None = None): - self.models = models or {} + start = (self.x, self.y) + goal = (gx, gy) + open_set = [(abs(start[0] - gx) + abs(start[1] - gy), 0, start, None, -1)] + came_from = {} + cost = {start: 0} + found = None - def infer(self, obs: np.ndarray) -> str: - return infer_difficulty(obs) + while open_set: + _, c, pos, prev, act = heapq.heappop(open_set) + if pos in came_from: + continue + came_from[pos] = (prev, act) + if pos == goal: + found = pos + break + for a, (dx, dy) in MOVE_DELTA.items(): + nx, ny = pos[0] + dx, pos[1] + dy + if not (0 <= nx < self.H and 0 <= ny < self.W): + continue + if (nx, ny) in self._obs: + continue + nc = c + 1 + if (nx, ny) not in cost or nc < cost[(nx, ny)]: + cost[(nx, ny)] = nc + heapq.heappush(open_set, (nc + abs(nx - gx) + abs(ny - gy), nc, (nx, ny), pos, a)) - def params(self, difficulty: str) -> ExpertParams: - return params_for(difficulty) + if found is None: + self._path_cache[cache_key] = None + return None - def model_for(self, difficulty: str) -> Any | None: - return self.models.get(difficulty) + acts = [] + cur = found + while cur != start: + prev, a = came_from[cur] + acts.append(a) + cur = prev + acts.reverse() - def drop_model(self, difficulty: str): - self.models.pop(difficulty, None) + # 缓存路径(限制缓存大小) + if len(self._path_cache) < 5000: + self._path_cache[cache_key] = acts - def available_models(self) -> list[str]: - return [name for name in DIFFICULTIES if name in self.models] + return acts + # ═══════════════════════════════════════════════════════════════════════════ + # 目标超时检测 + # ═══════════════════════════════════════════════════════════════════════════ -def market_base(index: int) -> int: - return 46 + int(index) * 7 + def _goal_timed_out(self): + if self._goal is None: + return False + gx, gy = self._goal + dist = abs(self.x - gx) + abs(self.y - gy) + if self._goal_steps == 0: + self._goal_start_dist = dist -def market_count(difficulty: str) -> int: - return MARKET_COUNT.get(difficulty, 3) + self._goal_steps += 1 + timeout = 120 + self._goal_start_dist * 5 + if self._goal_steps > timeout: + return True + if self._goal_steps > 40 and dist >= self._goal_start_dist: + return True + return False + + # ═══════════════════════════════════════════════════════════════════════════ + # 黑名单维护 + # ═══════════════════════════════════════════════════════════════════════════ + + def _blacklist_maintain(self): + expired = [p for p, t in self._black_t.items() if self._eps_steps - t > 800] + for p in expired: + self._black.discard(p) + del self._black_t[p] + while len(self._black) > 12: + old = min((p for p in self._black if p != (0, 0)), + key=lambda p: self._black_t.get(p, 0), default=None) + if old is None: + break + self._black.discard(old) + del self._black_t[old] + + def _blacklist(self, pos): + if pos and pos != (0, 0): + self._black.add(pos) + self._black_t[pos] = self._eps_steps + + # ═══════════════════════════════════════════════════════════════════════════ + # 导航 + # ═══════════════════════════════════════════════════════════════════════════ + + def _move_to(self, mask): + """向 _goal 移动一步。""" + if self._goal is None: + return None + gx, gy = self._goal -def map_size(difficulty: str) -> int: - return MAP_SIZE.get(difficulty, 10) + # 已到达 + if (self.x, self.y) == (gx, gy): + return None + # 超时检测 + if self._goal_timed_out(): + self._blacklist((gx, gy)) + self._goal = None + self._goal_act = None + return None -def market_distance(obs: np.ndarray, index: int, difficulty: str) -> float: - if index < 0 or index >= market_count(difficulty): - return 999.0 - base = market_base(index) - n = float(map_size(difficulty)) - return abs(float(obs[base]) * n) + abs(float(obs[base + 1]) * n) + # A* + path = self._astar(gx, gy) + if path and len(path) > 0 and mask[path[0]]: + return path[0] + + # 贪心兜底 + best, best_d = None, 999 + for a, (dx, dy) in MOVE_DELTA.items(): + if mask[a]: + nx, ny = self.x + dx, self.y + dy + if 0 <= nx < self.H and 0 <= ny < self.W: + d = abs(nx - gx) + abs(ny - gy) + if d < best_d: + best_d = d + best = a + if best is None: + fc = self._fail.get((gx, gy), 0) + 1 + self._fail[(gx, gy)] = fc + if fc >= 3: + self._blacklist((gx, gy)) + self._fail.pop((gx, gy), None) + self._goal = None + self._goal_act = None + return best + + def _set_goal(self, gx, gy, action=None): + """设置新目标并重置计时器。""" + self._goal = (gx, gy) if gx is not None else None + self._goal_act = action + self._goal_steps = 0 + if gx is not None: + self._goal_start_dist = abs(self.x - gx) + abs(self.y - gy) + self._replan = False + + # ═══════════════════════════════════════════════════════════════════════════ + # 探索(BFS 最近未访问格) + # ═══════════════════════════════════════════════════════════════════════════ + + def _explore(self): + self._cells.add((self.x, self.y)) + q = deque([(self.x, self.y)]) + vis = {(self.x, self.y)} + while q: + cx, cy = q.popleft() + if (cx, cy) not in self._cells and (cx, cy) not in self._obs: + return (cx, cy) + for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: + nx, ny = cx + dx, cy + dy + if 0 <= nx < self.H and 0 <= ny < self.W and (nx, ny) not in vis: + vis.add((nx, ny)) + q.append((nx, ny)) + return None -def market_is_adjacent(obs: np.ndarray, index: int, difficulty: str) -> bool: - return market_distance(obs, index, difficulty) <= 1.15 + # ═══════════════════════════════════════════════════════════════════════════ + # 套利系统(核心) + # ═══════════════════════════════════════════════════════════════════════════ + def _best_arbitrage(self, obs): + """找最佳套利机会。(buy_mid, sell_mid, pid, margin, profit_est) 或 None。""" + if len(self.mkts) < 2: + return None + prices = self._all_prices(obs) -def adjacent_market(obs: np.ndarray, difficulty: str) -> int | None: - candidates = [ - (market_distance(obs, idx, difficulty), idx) - for idx in range(market_count(difficulty)) - ] - if not candidates: - return None - dist, idx = min(candidates) - return idx if dist <= 1.15 else None - - -def price_at(obs: np.ndarray, market: int, pid: int, difficulty: str) -> float: - if market < 0 or market >= market_count(difficulty): - return 0.0 - base = market_base(market) - norm = float(obs[base + 2 + pid]) - # Markets beyond index 1 are hidden until market_analysis; zero means unknown. - if market >= 2 and not tech_owned(obs, 26) and abs(norm) < 1e-7: - return float(PRICE_LO[pid] + 0.5 * PRICE_RANGE[pid]) - return float(PRICE_LO[pid] + norm * PRICE_RANGE[pid]) - - -def best_visible_upside(obs: np.ndarray, buy_market: int, difficulty: str) -> float: - best = -1e9 - count = market_count(difficulty) - for pid in range(5): - buy_price = price_at(obs, buy_market, pid, difficulty) - sell_price = max( - price_at(obs, other, pid, difficulty) - for other in range(count) - if other != buy_market - ) - best = max(best, sell_price - buy_price) - return float(best) - - -def held_value_at(obs: np.ndarray, market: int, difficulty: str) -> float: - value = 0.0 - for pid in range(5): - value += max(0.0, float(obs[4 + pid])) * price_at(obs, market, pid, difficulty) - return float(value) - - -def best_sell_action(obs: np.ndarray, mask: np.ndarray, market: int | None, difficulty: str) -> int | None: - choices: list[tuple[float, int]] = [] - for action in SELL_ACTIONS: - if action >= len(mask) or not bool(mask[action]): - continue - pid = action - SELL_0 - price = price_at(obs, market, pid, difficulty) if market is not None else PRICE_LO[pid] - choices.append((float(obs[4 + pid]) * float(price), action)) - if not choices: - return None - return max(choices)[1] - - -def choose_buy_market(obs: np.ndarray, difficulty: str) -> int: - params = params_for(difficulty) - scores = [] - for idx in range(market_count(difficulty)): - upside = best_visible_upside(obs, idx, difficulty) - dist = market_distance(obs, idx, difficulty) - scores.append((upside - params.distance_penalty * dist, idx)) - return max(scores)[1] - - -def choose_sell_market(obs: np.ndarray, difficulty: str) -> int: - params = params_for(difficulty) - scores = [] - for idx in range(market_count(difficulty)): - value = held_value_at(obs, idx, difficulty) - dist = market_distance(obs, idx, difficulty) - scores.append((value - params.distance_penalty * dist, idx)) - return max(scores)[1] - - -def choose_market(obs: np.ndarray, prefer_sell: bool, difficulty: str) -> int: - if prefer_sell and product_inventory(obs) > 1e-6: - return choose_sell_market(obs, difficulty) - return choose_buy_market(obs, difficulty) - - -class TargetSelector: - def buy_market(self, obs: np.ndarray, difficulty: str) -> int: - return choose_buy_market(obs, difficulty) - - def sell_market(self, obs: np.ndarray, difficulty: str) -> int: - return choose_sell_market(obs, difficulty) - - def market(self, obs: np.ndarray, prefer_sell: bool, difficulty: str) -> int: - return choose_market(obs, prefer_sell, difficulty) - - def nearest_closed_compute_center(self, obs: np.ndarray, difficulty: str) -> tuple[float, int] | None: - candidates: list[tuple[float, int]] = [] - for idx in range(3): - base = 34 + idx * 4 - if float(obs[base + 2]) < 0.5: - dist = abs(float(obs[base]) * map_size(difficulty)) + abs(float(obs[base + 1]) * map_size(difficulty)) - if dist > 0.0: - candidates.append((dist, base)) - return min(candidates) if candidates else None - - -class PriceMemory: - def __init__(self, horizon: int = 12): - self.horizon = int(horizon) - self.history: dict[tuple[int, int], list[float]] = {} - - def reset(self): - self.history.clear() - - def observe(self, obs: np.ndarray, difficulty: str): - for market in range(market_count(difficulty)): - for pid in range(5): - value = price_at(obs, market, pid, difficulty) - key = (market, pid) - hist = self.history.setdefault(key, []) - hist.append(float(value)) - if len(hist) > self.horizon: - del hist[:-self.horizon] - - def trend(self, market: int, pid: int) -> float: - hist = self.history.get((market, pid), []) - if len(hist) < 3: - return 0.0 - return float(hist[-1] - hist[0]) - - -class OnlineNavigator: - def __init__(self): - self.visits: dict[tuple[int, int], int] = {} - self.last_pos: tuple[int, int] | None = None - self.last_action: int | None = None - self.stuck_steps = 0 - - def reset(self): - self.visits.clear() - self.last_pos = None - self.last_action = None - self.stuck_steps = 0 - - def _pos(self, obs: np.ndarray, difficulty: str) -> tuple[int, int]: - n = map_size(difficulty) - x = int(np.clip(round(float(obs[0]) * n), 0, n - 1)) - y = int(np.clip(round(float(obs[1]) * n), 0, n - 1)) - return x, y - - def observe(self, obs: np.ndarray, difficulty: str): - pos = self._pos(obs, difficulty) - if self.last_pos == pos and float(obs[9]) <= 1e-6: - self.stuck_steps += 1 - elif self.last_pos != pos: - self.stuck_steps = 0 - self.last_pos = pos - self.visits[pos] = self.visits.get(pos, 0) + 1 - - def move_toward(self, obs: np.ndarray, mask: np.ndarray, dx_norm: float, dy_norm: float, difficulty: str) -> int: - if float(obs[9]) > 0.0: - return WAIT - n = float(map_size(difficulty)) - dx = float(dx_norm) * n - dy = float(dy_norm) * n - if abs(dx) + abs(dy) <= 1.05: - return self.explore(obs, mask, difficulty) - - preferred: list[int] = [] - if abs(dx) >= abs(dy): - preferred.append(MOVE_DOWN if dx > 0 else MOVE_UP) - preferred.append(MOVE_RIGHT if dy > 0 else MOVE_LEFT) - else: - preferred.append(MOVE_RIGHT if dy > 0 else MOVE_LEFT) - preferred.append(MOVE_DOWN if dx > 0 else MOVE_UP) + best = None + best_score = float("-inf") - pos = self._pos(obs, difficulty) - ranked: list[tuple[float, int]] = [] - for action in MOVE_DELTAS: - if action >= len(mask) or not mask[action]: + for bmid, bp in prices.items(): + bx, by = self.mkts[bmid] + if (bx, by) in self._black: continue - ddx, ddy = MOVE_DELTAS[action] - new_dx = dx - ddx - new_dy = dy - ddy - new_pos = (pos[0] + ddx, pos[1] + ddy) - reverse_penalty = 0.35 if self._is_reverse(action) else 0.0 - preferred_bonus = -0.25 if action in preferred else 0.0 - visit_penalty = 0.08 * self.visits.get(new_pos, 0) - stuck_escape = -0.75 if self.stuck_steps >= 2 and not self._is_reverse(action) else 0.0 - score = abs(new_dx) + abs(new_dy) + reverse_penalty + visit_penalty + preferred_bonus + stuck_escape - ranked.append((score, action)) - if ranked: - action = min(ranked)[1] - self.last_action = action - return action - return WAIT if mask[WAIT] else int(_valid_indices(mask)[0]) - - def explore(self, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int: - if float(obs[9]) > 0.0: - return WAIT - pos = self._pos(obs, difficulty) - choices = [] - for action, (dx, dy) in MOVE_DELTAS.items(): - if action < len(mask) and mask[action]: - new_pos = (pos[0] + dx, pos[1] + dy) - score = self.visits.get(new_pos, 0) + (0.5 if self._is_reverse(action) else 0.0) - choices.append((score, action)) - if choices: - action = min(choices)[1] - self.last_action = action - return action - if HARVEST < len(mask) and mask[HARVEST]: - return HARVEST - return WAIT - - def _is_reverse(self, action: int) -> bool: - pairs = { - MOVE_UP: MOVE_DOWN, - MOVE_DOWN: MOVE_UP, - MOVE_LEFT: MOVE_RIGHT, - MOVE_RIGHT: MOVE_LEFT, - } - return self.last_action is not None and pairs.get(action) == self.last_action - - -def build_macro_observation( - obs: np.ndarray, - primitive_mask: np.ndarray, - difficulty: str = "medium", - memory: PriceMemory | None = None, -) -> np.ndarray: - features = np.zeros(MACRO_OBS_DIM, dtype=np.float32) - obs_arr = np.asarray(obs, dtype=np.float32) - mask_arr = np.asarray(primitive_mask, dtype=np.float32) - features[:OBS_DIM] = obs_arr[:OBS_DIM] - features[OBS_DIM : OBS_DIM + N_PRIMITIVE_ACTIONS] = mask_arr[:N_PRIMITIVE_ACTIONS] - base = 110 - for i, name in enumerate(DIFFICULTIES): - features[base + i] = 1.0 if difficulty == name else 0.0 - features[113] = np.clip(product_inventory(obs_arr), 0.0, 2.0) - features[114] = np.clip(total_inventory(obs_arr), 0.0, 2.0) - features[115] = np.clip(money_from_obs(obs_arr) / 250.0, 0.0, 4.0) - features[116] = np.clip(compute_from_obs(obs_arr) / 120.0, 0.0, 3.0) - features[117] = time_ratio(obs_arr) - adj = adjacent_market(obs_arr, difficulty) - features[118] = -1.0 if adj is None else float(adj) / 3.0 - - offset = 120 - for idx in range(4): - if idx < market_count(difficulty): - features[offset] = np.clip(market_distance(obs_arr, idx, difficulty) / 20.0, 0.0, 2.0) - features[offset + 1] = np.clip(best_visible_upside(obs_arr, idx, difficulty) / 100.0, -2.0, 2.0) - features[offset + 2] = np.clip(held_value_at(obs_arr, idx, difficulty) / 120.0, 0.0, 3.0) - if memory is not None: - trends = [memory.trend(idx, pid) for pid in range(5)] - features[offset + 3] = np.clip(max(trends) / 30.0, -2.0, 2.0) - features[offset + 4] = 1.0 if market_is_adjacent(obs_arr, idx, difficulty) else 0.0 - offset += 5 - - for i, action in enumerate(TECH_ACTIONS): - features[140 + i] = 1.0 if tech_owned(obs_arr, action) else 0.0 - hint = expert_macro_hint(obs_arr, primitive_mask, difficulty, memory) - if 0 <= hint < MACRO_ACTION_COUNT: - features[148 + hint] = 1.0 - return features - - -def build_macro_action_mask(obs: np.ndarray, primitive_mask: np.ndarray, difficulty: str = "medium") -> np.ndarray: - mask = np.zeros(MACRO_ACTION_COUNT, dtype=bool) - inv = product_inventory(obs) - params = params_for(difficulty) - count = market_count(difficulty) - mask[FOLLOW_EXPERT] = True - for idx in range(count): - mask[BUY_MARKET_0 + idx] = inv < params.buy_fill - mask[SELL_MARKET_0 + idx] = inv > 1e-6 - mask[FACTORY_PLAN] = True - mask[OCCUPY_NEAREST] = bool(primitive_mask[OCCUPY]) or time_ratio(obs) < params.occupy_until - mask[WAIT_FOR_PRICE] = inv > 1e-6 and time_ratio(obs) < params.wait_until_time - mask[ENDGAME_LIQUIDATE] = inv > 1e-6 - return mask - - -def expert_macro_hint( - obs: np.ndarray, - primitive_mask: np.ndarray, - difficulty: str, - memory: PriceMemory | None = None, -) -> int: - params = params_for(difficulty) - inv = product_inventory(obs) - if inv > 1e-6 and time_ratio(obs) >= params.endgame_time: - return ENDGAME_LIQUIDATE - if inv > 1e-6: - target = choose_sell_market(obs, difficulty) - return SELL_MARKET_0 + min(target, 3) - target = choose_buy_market(obs, difficulty) - return BUY_MARKET_0 + min(target, 3) - - -class HybridController: - def __init__(self): - self.navigator = OnlineNavigator() - self.price_memory = PriceMemory() - self.targets = TargetSelector() - self.current_option: int | None = None - self.option_steps = 0 - self.no_trade_steps = 0 - self.prev_signature: tuple[float, ...] | None = None - - def reset(self): - self.navigator.reset() - self.price_memory.reset() - self.current_option = None - self.option_steps = 0 - self.no_trade_steps = 0 - self.prev_signature = None - - def observe(self, obs: np.ndarray, difficulty: str): - self.navigator.observe(obs, difficulty) - self.price_memory.observe(obs, difficulty) - sig = tuple(np.round(np.asarray(obs[3:12], dtype=float), 4)) - if self.prev_signature is not None and sig == self.prev_signature: - self.no_trade_steps += 1 - else: - self.no_trade_steps = 0 - self.prev_signature = sig - - def start_option(self, macro_action: int): - self.current_option = int(macro_action) - self.option_steps = 0 - - def macro_observation(self, obs: np.ndarray, primitive_mask: np.ndarray, difficulty: str) -> np.ndarray: - return build_macro_observation(obs, primitive_mask, difficulty, self.price_memory) + for smid, sp in prices.items(): + if bmid == smid: + continue + sx, sy = self.mkts[smid] + if (sx, sy) in self._black: + continue + for pid in range(5): + buy_p = bp.get(pid, 0) + sell_p = sp.get(pid, 0) + if buy_p <= 0 or sell_p <= buy_p * 1.02: + continue + margin = sell_p - buy_p + # 综合评分:利润率 - 距离惩罚 + profit_rate = margin / max(buy_p, 1) + travel = abs(self.x - bx) + abs(self.y - by) + abs(bx - sx) + abs(by - sy) + # 有效的单步利润率(travel cost per unit is amortized over capacity) + cap = self._capacity(obs) + # 能买多少单位 + affordable = int(self.money / max(buy_p, 1)) if self.money > 0 else 0 + units = min(affordable, int(cap)) + if units <= 0: + continue + total_profit = units * margin + # 评分:单步期望收益(buy: units*2 tick, sell: 一次卖全部仅2 tick) + steps_est = travel + units * 2 + 2 + if steps_est <= 0: + continue + score = total_profit / steps_est + if score > best_score: + best_score = score + best = (bmid, smid, pid, margin, total_profit, buy_p, sell_p, units) - def macro_action_mask(self, obs: np.ndarray, primitive_mask: np.ndarray, difficulty: str) -> np.ndarray: - return build_macro_action_mask(obs, primitive_mask, difficulty) + return best - def expert_action(self, obs: np.ndarray, primitive_mask: np.ndarray, difficulty: str) -> int: - mask = np.asarray(primitive_mask, dtype=bool) - if float(obs[9]) > 0.0: - return WAIT - params = params_for(difficulty) - current_market = adjacent_market(obs, difficulty) - sell_action = best_sell_action(obs, mask, current_market, difficulty) - inv = product_inventory(obs) - - if inv > 1e-6 and time_ratio(obs) >= params.endgame_time: - if sell_action is not None: - return sell_action - return self._go_to_market(self.targets.sell_market(obs, difficulty), obs, mask, difficulty) - - if sell_action is not None and self._should_sell_now(obs, current_market, difficulty): - return sell_action - - factory_action = self._factory_action(obs, mask, difficulty) - if factory_action is not None: - return factory_action - - has_raw = float(obs[3]) > 0.05 - has_factory_stock = bool(np.sum(np.clip(obs[16:21], 0.0, 2.0)) > 1e-6) - if time_ratio(obs) < params.factory_until and (has_raw or has_factory_stock): - return self._factory_plan(obs, mask, difficulty) - - if inv < params.buy_fill and BUY < len(mask) and mask[BUY]: - return BUY - - if inv > 1e-6: - return self._go_to_market(self.targets.sell_market(obs, difficulty), obs, mask, difficulty) - - if HARVEST < len(mask) and mask[HARVEST] and (money_from_obs(obs) < 8.0 or time_ratio(obs) < 0.18): - return HARVEST - - if self.no_trade_steps > params.explore_after: - return self.navigator.explore(obs, mask, difficulty) - return self._go_to_market(self.targets.buy_market(obs, difficulty), obs, mask, difficulty) - - def primitive_for_macro( - self, - macro_action: int, - obs: np.ndarray, - primitive_mask: np.ndarray, - difficulty: str, - ) -> int: - self.option_steps += 1 - macro_action = int(macro_action) - if macro_action == FOLLOW_EXPERT: - return self.expert_action(obs, primitive_mask, difficulty) - if BUY_MARKET_0 <= macro_action <= BUY_MARKET_3: - return self._buy_at_market(macro_action - BUY_MARKET_0, obs, primitive_mask, difficulty) - if SELL_MARKET_0 <= macro_action <= SELL_MARKET_3: - return self._sell_at_market(macro_action - SELL_MARKET_0, obs, primitive_mask, difficulty) - if macro_action == FACTORY_PLAN: - return self._factory_plan(obs, primitive_mask, difficulty) - if macro_action == OCCUPY_NEAREST: - return self._occupy_plan(obs, primitive_mask, difficulty) - if macro_action == WAIT_FOR_PRICE: - if time_ratio(obs) > params_for(difficulty).wait_until_time: - return self.expert_action(obs, primitive_mask, difficulty) - return WAIT if primitive_mask[WAIT] else self.expert_action(obs, primitive_mask, difficulty) - if macro_action == ENDGAME_LIQUIDATE: - return self._sell_at_market(self.targets.sell_market(obs, difficulty), obs, primitive_mask, difficulty) - return self.expert_action(obs, primitive_mask, difficulty) - - def option_complete(self, macro_action: int, obs: np.ndarray, last_primitive: int, difficulty: str) -> bool: - if last_primitive in (BUY, LOAD, DEPOSIT, OCCUPY) or SELL_0 <= last_primitive <= SELL_4: - return True - if macro_action == WAIT_FOR_PRICE: - return self.option_steps >= 3 - if macro_action == FACTORY_PLAN: - return self.option_steps >= 12 - if macro_action == OCCUPY_NEAREST: - return self.option_steps >= 18 or bool(last_primitive == OCCUPY) - return self.option_steps >= self.option_limit(macro_action) - - def option_limit(self, macro_action: int) -> int: - if BUY_MARKET_0 <= macro_action <= SELL_MARKET_3: - return 18 - if macro_action == ENDGAME_LIQUIDATE: - return 24 - if macro_action == FACTORY_PLAN: - return 18 - return 8 - - def _should_sell_now(self, obs: np.ndarray, market: int | None, difficulty: str) -> bool: - if market is None: - return False - if time_ratio(obs) >= params_for(difficulty).wait_until_time: - return True - current = held_value_at(obs, market, difficulty) - best = max(held_value_at(obs, idx, difficulty) for idx in range(market_count(difficulty))) - trend_bonus = 0.0 - for pid in range(5): - if obs[4 + pid] > 1e-6: - trend_bonus = max(trend_bonus, self.price_memory.trend(market, pid)) - return current + params_for(difficulty).sell_margin >= best or trend_bonus < -1.5 - - def _go_to_market(self, index: int, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int: - index = int(np.clip(index, 0, market_count(difficulty) - 1)) - base = market_base(index) - return self.navigator.move_toward(obs, mask, float(obs[base]), float(obs[base + 1]), difficulty) - - def _buy_at_market(self, index: int, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int: - if index >= market_count(difficulty): - return self.expert_action(obs, mask, difficulty) - if market_is_adjacent(obs, index, difficulty) and mask[BUY] and product_inventory(obs) < params_for(difficulty).buy_fill: - return BUY - return self._go_to_market(index, obs, mask, difficulty) - - def _sell_at_market(self, index: int, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int: - if index >= market_count(difficulty): - index = self.targets.sell_market(obs, difficulty) - current = adjacent_market(obs, difficulty) - if current == index: - sell_action = best_sell_action(obs, mask, current, difficulty) - if sell_action is not None: - return sell_action - return self._go_to_market(index, obs, mask, difficulty) - - def _factory_action(self, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int | None: - if float(obs[0]) > 0.04 or float(obs[1]) > 0.04: - return None - params = params_for(difficulty) - if time_ratio(obs) > params.factory_until: - if LOAD < len(mask) and mask[LOAD]: - return LOAD + def _best_sell_market(self, obs, avoid_mid=None): + """为身上产品找到最佳卖出市场。""" + prod_inv = self._prod_inv(obs) + if not prod_inv: return None - if DEPOSIT < len(mask) and mask[DEPOSIT]: - return DEPOSIT - if LOAD < len(mask) and mask[LOAD] and product_inventory(obs) < params.buy_fill: - return LOAD - for tech in params.tech_priority: - if tech < len(mask) and mask[tech]: - return tech - produce = self._best_produce_action(obs, mask, difficulty) - if produce is not None: - return produce - return None - def _factory_plan(self, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int: - action = self._factory_action(obs, mask, difficulty) - if action is not None: - return action - return self.navigator.move_toward(obs, mask, -float(obs[0]), -float(obs[1]), difficulty) - - def _occupy_plan(self, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int: - if OCCUPY < len(mask) and mask[OCCUPY]: - return OCCUPY - center = self.targets.nearest_closed_compute_center(obs, difficulty) - if center is not None: - _, base = center - return self.navigator.move_toward(obs, mask, float(obs[base]), float(obs[base + 1]), difficulty) - return self.expert_action(obs, mask, difficulty) - - def _best_produce_action(self, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int | None: - best: tuple[float, int] | None = None - for action in PRODUCE_ACTIONS: - if action >= len(mask) or not mask[action]: - continue - pid = action - PRODUCE_0 - best_price = max(price_at(obs, market, pid, difficulty) for market in range(market_count(difficulty))) - score = best_price / max(1.0, float(RAW_COST[pid])) - if best is None or score > best[0]: - best = (score, action) - return None if best is None else best[1] - - -class PureArbitrageController: - def __init__(self, env: Any): - self.env = env - self.fallback = HybridController() - self.last_time = -1.0 - - def reset(self): - self.fallback.reset() - self.last_time = -1.0 - self._forecast = None - self._forecast_episode = None - - def action(self, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int: - self.fallback.observe(obs, difficulty) - if float(obs[9]) > 0.0: - return WAIT - if not self._has_world(): - return self.fallback.expert_action(obs, mask, difficulty) + prices = self._all_prices(obs) + best = None + best_total = 0 - env = self.env - unit = env.unit - current_time = time_ratio(obs) - - sell_action = self._best_adjacent_sell(mask) - force_sell_time = {"easy": 0.90, "medium": 0.90, "hard": 1.10}.get(difficulty, 0.90) - if sell_action is not None and (current_time > force_sell_time or unit.free_capacity <= 0): - return sell_action + for mid, mp in prices.items(): + if mid == avoid_mid: + continue + mx, my = self.mkts[mid] + if (mx, my) in self._black: + continue + total = 0 + sellable = 0 + for pid, qty in prod_inv.items(): + price = mp.get(pid, 0) + if price > 0: + total += qty * price + sellable += qty + if sellable > 0 and total > best_total: + best_total = total + d = abs(self.x - mx) + abs(self.y - my) + best = (mid, total, sellable, d) + + return best + + # ═══════════════════════════════════════════════════════════════════════════ + # 算力中心与科技 + # ═══════════════════════════════════════════════════════════════════════════ + + def _nearest_closed_center(self): + """返回最近的未占领算力中心。""" + best_cid = None + best_d = 999 + for cid, (cx, cy) in self.ctrs.items(): + if cid in self._occupied: + continue + if (cx, cy) in self._black: + continue + path = self._astar(cx, cy) + if path is None: + self._blacklist((cx, cy)) + continue + d = abs(self.x - cx) + abs(self.y - cy) + if d < best_d: + best_d = d + best_cid = cid + return best_cid + + def _next_tech_to_buy(self, obs): + """返回下一个应该购买的科技 TECH_x ID(mask 已检查),或 None。""" + techs = self._techs_owned(obs) + for key in TECH_PRIORITY: + tid = TECH_KEY_TO_ID[key] + idx = tid - TECH_0 + if techs[idx]: + continue # 已拥有 + # 检查失败次数(避免死循环) + fails = self._tech_attempted.get(key, 0) + if fails >= 5: + continue + return tid + return None + def _should_get_techs(self, obs, mask): + """判断是否应该去工厂买科技。""" + # 已经有 path_optimization → 不需要 + techs = self._techs_owned(obs) + if techs[5] and techs[3]: + return False + if self._tech_attempted.get("path_optimization", 0) >= 5: + return False + # 在工厂且 mask 允许科技购买 + if not self._at_factory(): + return False + tid = self._next_tech_to_buy(obs) + if tid is None or not mask[tid]: + return False + return True + + # ═══════════════════════════════════════════════════════════════════════════ + # 主策略 + # ═══════════════════════════════════════════════════════════════════════════ + + def _plan(self, obs, mask): + self._blacklist_maintain() + + techs = self._techs_owned(obs) + has_prod = self._has_prod(obs) + prod_inv = self._prod_inv(obs) + prod_qty = sum(prod_inv.values()) + has_path_opt = techs[5] + cap = self._capacity(obs) + + # 站哪个市场旁? + at_mid = self._which_market_adjacent() + + # ═══════════════════════════════════════════════════════════════════════ + # P0: 在买入市场 → 继续批量买入(直到满了或没钱了再走) + # ═══════════════════════════════════════════════════════════════════════ + if has_prod and at_mid is not None and at_mid == self._last_buy_mid: + # 在买入市场,检查能否继续买 + if mask[BUY] and prod_qty < cap and self.money >= 1.0: + self._state = "ARB_BUY" + self._set_goal(None, None, BUY) + return + + # ═══════════════════════════════════════════════════════════════════════ + # P1: 在非买入市场旁 → 卖出手持产品 + # ═══════════════════════════════════════════════════════════════════════ + if has_prod and at_mid is not None and at_mid != self._last_buy_mid: + for pid in list(prod_inv.keys()): + if mask[SELL_0 + pid]: + self._state = "SELL" + self._set_goal(None, None, SELL_0 + pid) + return + best_sell = self._best_sell_market(obs, avoid_mid=self._last_buy_mid) + if best_sell: + self._state = "GO_SELL" + self._set_goal(*self.mkts[best_sell[0]], None) + return + + # ═══════════════════════════════════════════════════════════════════════ + # P1.5: 在工厂 → 买科技或等待算力 + # ═══════════════════════════════════════════════════════════════════════ if self._at_factory(): - tech = self._factory_tech(mask, difficulty, current_time) - if tech is not None: - return tech - if LOAD < len(mask) and mask[LOAD] and unit.free_capacity > 0: - return LOAD - if DEPOSIT < len(mask) and mask[DEPOSIT]: - return DEPOSIT - produce = self._produce_action(mask) - if produce is not None and current_time < 0.72: - return produce - - refill_until = {"easy": 0.995, "medium": 0.990, "hard": 0.99}.get(difficulty, 0.90) - if self._carrying_products() and unit.free_capacity > self._min_free_before_sell(difficulty) and current_time < refill_until: - buy_plan = self._best_buy_market(difficulty) - if buy_plan is not None and buy_plan[1] > 0.25: - market_id, _profit = buy_plan - if self._adjacent_market_id() == market_id and BUY < len(mask) and mask[BUY]: - return BUY - action = self._move_to_market(market_id, mask) - if action is not None: - return action - - if ( - difficulty == "hard" - and current_time < 0.55 - and float(getattr(env, "compute", 0.0)) >= 80.0 - and abs(int(env.unit.x) - int(env.cfg.factory_x)) + abs(int(env.unit.y) - int(env.cfg.factory_y)) <= 15 - and not self._at_factory() - ): - action = self._move_to_factory(mask) - if action is not None: - return action - - if ( - difficulty == "easy" - and current_time < 0.90 - and float(getattr(env, "compute", 0.0)) >= 80.0 - and abs(int(env.unit.x) - int(env.cfg.factory_x)) + abs(int(env.unit.y) - int(env.cfg.factory_y)) <= 6 - and not self._at_factory() - ): - action = self._move_to_factory(mask) - if action is not None: - return action - - if ( - difficulty == "medium" - and current_time < 0.90 - and float(getattr(env, "compute", 0.0)) >= 80.0 - and abs(int(env.unit.x) - int(env.cfg.factory_x)) + abs(int(env.unit.y) - int(env.cfg.factory_y)) <= 8 - and not self._at_factory() - ): - action = self._move_to_factory(mask) - if action is not None: - return action - - if self._carrying_products(): - if sell_action is not None and self._should_sell_here(obs, difficulty): - return sell_action - target = self._best_sell_market(difficulty) - if target is not None: - action = self._move_to_market(target, mask) - if action is not None: - return action - - if self._carrying_raw(): - action = self._move_to_factory(mask) - if action is not None: - return action - - if ( - difficulty == "hard" - and current_time < 0.55 - and float(getattr(env, "compute", 0.0)) >= 80.0 - and not self._carrying_products() - and not self._carrying_raw() - and not self._at_factory() - ): - action = self._move_to_factory(mask) - if action is not None: - return action - - if ( - difficulty == "hard" - and current_time < 0.30 - and float(getattr(env, "compute", 0.0)) >= 30.0 - and not self._carrying_products() - and not self._carrying_raw() - and not self._at_factory() - ): - action = self._move_to_factory(mask) - if action is not None: - return action - - if ( - difficulty == "medium" - and current_time < 0.90 - and float(getattr(env, "compute", 0.0)) >= 80.0 - and abs(int(env.unit.x) - int(env.cfg.factory_x)) + abs(int(env.unit.y) - int(env.cfg.factory_y)) <= 8 - and not self._at_factory() - ): - action = self._move_to_factory(mask) - if action is not None: - return action - - if self._factory_has_products() and unit.free_capacity > 2 and current_time < 0.86: - action = self._move_to_factory(mask) - if action is not None: - return action - - if self._factory_can_produce() and current_time < 0.72: - action = self._move_to_factory(mask) - if action is not None: - return action - - if ( - (difficulty == "easy" and current_time < 0.10) - or (difficulty == "medium" and current_time < 0.15) - or (difficulty == "hard" and current_time < 0.06) - ): - occupy = self._compute_center_plan(mask) - if occupy is not None: - return occupy - - if unit.free_capacity <= 1: - target = self._best_sell_market(difficulty) - if target is not None: - action = self._move_to_market(target, mask) - if action is not None: - return action - - buy_until = {"easy": 0.98, "medium": 0.99, "hard": 0.970}.get(difficulty, 0.95) - if unit.free_capacity > 1 and current_time < buy_until: - buy_plan = self._best_buy_market(difficulty) - if buy_plan is not None and (buy_plan[1] >= self._trade_profit_floor(difficulty) or current_time > 0.55): - market_id, _profit = buy_plan - if self._adjacent_market_id() == market_id and BUY < len(mask) and mask[BUY]: - return BUY - action = self._move_to_market(market_id, mask) - if action is not None: - return action - - resource = self._resource_plan(mask, difficulty, current_time) - if resource is not None: - return resource - - target = self._best_sell_market(difficulty) if self._carrying_products() else None - if target is not None: - action = self._move_to_market(target, mask) - if action is not None: - return action - return self.fallback.expert_action(obs, mask, difficulty) - - def _has_world(self) -> bool: - return all(hasattr(self.env, name) for name in ("unit", "board", "markets", "money", "factory")) - - def _at_factory(self) -> bool: - return bool(self.env.board.at_factory(self.env.unit.x, self.env.unit.y)) - - def _carrying_products(self) -> bool: - return any(qty > 1e-9 for qty in self.env.unit.prod_inv.values()) - - def _carrying_raw(self) -> bool: - return float(getattr(self.env.unit, "raw_inv", 0.0)) > 1e-9 - - def _factory_has_products(self) -> bool: - return float(getattr(self.env.factory, "total_product_stock", 0.0)) > 1e-9 - - def _factory_can_produce(self) -> bool: - raw = float(getattr(self.env.factory, "raw_stock", 0.0)) - return any(raw >= float(cost) for cost in RAW_COST) - - def _price_multiplier(self) -> float: - try: - return float(self.env.factory.price_multiplier) - except Exception: - return 1.0 - - def _effective_buy_price(self, market: Any, pid: int) -> float: - return max(0.0, float(market.get_price(pid)) + float(getattr(self.env.factory, "cost_delta", 0.0))) - - def _ensure_price_forecast(self): - if getattr(self, "_forecast_episode", None) == id(self.env.markets) and getattr(self, "_forecast", None) is not None: - return - try: - import random as _random - dt = float(self.env.cfg.time_step) - steps = int(getattr(self.env.cfg, "max_steps", 2000)) + 200 - markets = self.env.markets - prices = [[float(m._current_prices[pid]) for pid in range(5)] for m in markets] - rngs = [m._rng.getstate() for m in markets] - params = [m._ou_params for m in markets] - forecast = [] - for _ in range(steps + 1): - forecast.append([row[:] for row in prices]) - for mi in range(len(markets)): - rng = _random.Random(); rng.setstate(rngs[mi]) - for pid in range(5): - p = params[mi][pid] - cur = prices[mi][pid] - drift = 0.05 * (p["mean"] - cur) * dt - noise = rng.gauss(0, p["sigma"] * (dt ** 0.5)) - prices[mi][pid] = max(p["lo"], min(p["hi"], cur + drift + noise)) - rngs[mi] = rng.getstate() - self._forecast = forecast - self._forecast_episode = id(self.env.markets) - except Exception: - self._forecast = None - self._forecast_episode = id(self.env.markets) - - def _forecast_price(self, market_id: int, pid: int, tick: int) -> float: - forecast = getattr(self, "_forecast", None) - if forecast is None: - return float(self.env.markets[market_id].get_price(pid)) - idx = max(0, min(int(tick), len(forecast) - 1)) - return float(forecast[idx][market_id][pid]) - - def _move_ticks(self, dist: int) -> int: - return int(max(0, dist) if "path_optimization" in getattr(self.env, "_techs_owned", set()) else 2 * max(0, dist)) - - def install_buy_policy(self, difficulty: str): - if difficulty not in ("easy", "medium", "hard") or not self._has_world(): + tid = self._next_tech_to_buy(obs) + if tid is not None and mask[tid]: + self._state = "TECH" + self._set_goal(None, None, tid) + return + # 还需要科技但算力不够→在工厂等待算力积累(避免第二趟往返) + if tid is not None and self._occupied and not has_prod: + self._state = "WAIT_COMPUTE" + self._goal = None + self._goal_act = None + return + + # ═══════════════════════════════════════════════════════════════════════ + # P2: 需要核心科技且有足够算力 → 回工厂(仅一次) + # ═══════════════════════════════════════════════════════════════════════ + need_tech = (not techs[1]) or (not techs[5]) or (not techs[3]) + if need_tech and self.compute >= 90 and not self._at_factory(): + path = self._astar(0, 0) + if path is not None and len(path) <= 20: + self._state = "GO_FACTORY" + self._set_goal(0, 0, None) + return + + # ═══════════════════════════════════════════════════════════════════════ + # P3: 有产品但不在市场 → 去最佳卖出市场 + # ═══════════════════════════════════════════════════════════════════════ + if has_prod and at_mid is None: + avoid = self._last_buy_mid if self._has_bought else None + best_sell = self._best_sell_market(obs, avoid_mid=avoid) + if best_sell: + self._state = "GO_SELL" + self._set_goal(*self.mkts[best_sell[0]], None) + return + + # ═══════════════════════════════════════════════════════════════════════ + # P3: 在市场旁且空手 → 开始批量买入 + # ═══════════════════════════════════════════════════════════════════════ + if not has_prod and at_mid is not None and mask[BUY] and self.money >= 1.0: + self._state = "ARB_BUY" + self._last_buy_mid = at_mid + self._has_bought = True + self._set_goal(None, None, BUY) return - env = self.env - self._ensure_price_forecast() - - def best_buyable(mkt: Any): - best_pid = None - best_price = None - best_score = -1e18 - mid = int(mkt.id) - now = int(getattr(env, "_step", 0)) - mult = self._price_multiplier() - fill = int(max(1, min(float(env.unit.free_capacity), 35.0))) - buy_done_tick = now + 2 * fill - product_ids = (0, 3) if difficulty == "easy" else (((0, 1, 3) if float(getattr(self.env, "money", 0.0)) < 3000.0 else (0,)) if difficulty == "medium" else (0, 1, 3)) - for pid in product_ids: - effective = max(0.0, float(mkt.get_price(pid)) + float(getattr(env.factory, "cost_delta", 0.0))) - if float(env.money) < effective: + + # ═══════════════════════════════════════════════════════════════════════ + # P4: 未占领任何中心 → 主动去最近的计算中心(开局最关键!) + # ═══════════════════════════════════════════════════════════════════════ + if not self._occupied and self.ctrs and not has_prod: + cid = self._nearest_closed_center() + if cid is not None: + path = self._astar(*self.ctrs[cid]) + if path is not None: + self._state = "GO_CTR" + self._set_goal(*self.ctrs[cid], None) + return + + # ═══════════════════════════════════════════════════════════════════════ + # P6: 空手 → 找最佳套利对 → 去买入市场 + # ═══════════════════════════════════════════════════════════════════════ + if not has_prod and len(self.mkts) >= 2: + arb = self._best_arbitrage(obs) + if arb and arb[4] > 2: # 降低门槛,微小利润也能积累 + bmid = arb[0] + bx, by = self.mkts[bmid] + self._state = "ARB_GO_BUY" + self._set_goal(bx, by, None) + return + + # ═══════════════════════════════════════════════════════════════════════ + # P7: 有产品但没找到卖点 → 去最近非买入市场(兜底) + # ═══════════════════════════════════════════════════════════════════════ + if has_prod and self.mkts: + best_mid = None + best_d = 999 + for mid, (mx, my) in self.mkts.items(): + if mid == self._last_buy_mid: continue - best_sell = 0.0 - for other in env.markets: - oid = int(other.id) - if oid == mid: - continue - dist = abs(int(other.x) - int(mkt.x)) + abs(int(other.y) - int(mkt.y)) - tick = buy_done_tick + self._move_ticks(dist) - best_sell = max(best_sell, self._forecast_price(oid, pid, tick) * mult) - profit = best_sell - effective - if profit <= (0.0 if difficulty == "hard" else 0.5): + if (mx, my) in self._black: + continue + d = abs(self.x - mx) + abs(self.y - my) + if d < best_d: + best_d = d + best_mid = mid + if best_mid is not None: + self._state = "GO_SELL" + self._set_goal(*self.mkts[best_mid], None) + return + + # ═══════════════════════════════════════════════════════════════════════ + # P8: 探索/去最近市场 + # ═══════════════════════════════════════════════════════════════════════ + if self.mkts: + best_mid = None + best_score = -999 + for mid, (mx, my) in self.mkts.items(): + if (mx, my) in self._black: continue - score = self._buy_unit_score(profit, best_sell, difficulty) + d = max(1, abs(self.x - mx) + abs(self.y - my)) + score = 50.0 / d if score > best_score: best_score = score - best_pid = pid - best_price = effective - return best_pid, best_price - - env._best_buyable = best_buyable - - def _buy_unit_score(self, profit: float, sell: float, difficulty: str) -> float: - if difficulty == "easy" and float(getattr(self.env, "money", 0.0)) >= 0.0: - return float(profit) + 1.00 * float(sell) - if difficulty == "medium" and float(getattr(self.env, "money", 0.0)) >= 300.0: - return float(profit) + 0.80 * float(sell) - if difficulty == "hard" and float(getattr(self.env, "money", 0.0)) >= 500.0: - return float(profit) + 0.80 * float(sell) - return float(profit) - - def _best_adjacent_sell(self, mask: np.ndarray) -> int | None: - market_id = self._adjacent_market_id() - if market_id is None: - return None - market = self.env.markets[market_id] - best: tuple[float, int] | None = None - for action in SELL_ACTIONS: - if action >= len(mask) or not bool(mask[action]): - continue - pid = action - SELL_0 - qty = max(0.0, float(self.env.unit.prod_inv.get(pid, 0.0)) - float(self.env.unit.origin_qty(pid, market_id))) - if qty <= 1e-9: - continue - value = qty * float(market.get_price(pid, self._price_multiplier())) - if best is None or value > best[0]: - best = (value, action) - return None if best is None else best[1] - - def _should_sell_here(self, obs: np.ndarray, difficulty: str) -> bool: - here = self._adjacent_market_id() - if here is None: - return False - here_value = self._sell_value_at(here) - best = max((self._sell_value_at(i) for i in range(len(self.env.markets))), default=0.0) - slack = {"easy": 0.20, "medium": 0.35, "hard": 0.40}.get(difficulty, 0.35) - if time_ratio(obs) > 0.82: - slack -= 0.08 - return here_value >= best * slack - - def _sell_value_at(self, market_id: int) -> float: - market = self.env.markets[market_id] - value = 0.0 - for pid, qty_raw in self.env.unit.prod_inv.items(): - qty = max(0.0, float(qty_raw) - float(self.env.unit.origin_qty(pid, market_id))) - if qty > 0.0: - value += qty * float(market.get_price(pid, self._price_multiplier())) - return value - - def _best_sell_market(self, difficulty: str) -> int | None: - best: tuple[float, int] | None = None - now = int(getattr(self.env, "_step", 0)) - mult = self._price_multiplier() - for idx in range(len(self.env.markets)): - dist = self._distance_to_market(idx) - tick = now + self._move_ticks(dist) - value = 0.0 - for pid, qty_raw in self.env.unit.prod_inv.items(): - qty = max(0.0, float(qty_raw) - float(self.env.unit.origin_qty(pid, idx))) - if qty > 0.0: - value += qty * self._forecast_price(idx, pid, tick) * mult - if value <= 0.0: - continue - sell_dist_penalty = 0.0 if difficulty == "medium" else 1.0 - score = value - sell_dist_penalty * dist - if best is None or score > best[0]: - best = (score, idx) - return None if best is None else best[1] - - def _best_buy_market(self, difficulty: str) -> tuple[int, float] | None: - best: tuple[float, int, float] | None = None - money = float(self.env.money) - mult = self._price_multiplier() - for idx, market in enumerate(self.env.markets): - local_best = 0.0 - product_ids = (0, 3) if difficulty == "easy" else (((0, 1, 3) if float(getattr(self.env, "money", 0.0)) < 3000.0 else (0,)) if difficulty == "medium" else (0, 1, 3)) - for pid in product_ids: - buy = self._effective_buy_price(market, pid) - if money < buy: - continue - now = int(getattr(self.env, "_step", 0)) - fill = int(max(1, min(float(self.env.unit.free_capacity), 35.0))) - sell = 0.0 - for other in self.env.markets: - if int(other.id) == int(market.id): - continue - dist2 = abs(int(other.x) - int(market.x)) + abs(int(other.y) - int(market.y)) - tick = now + self._move_ticks(self._distance_to_market(idx)) + 2 * fill + self._move_ticks(dist2) - sell = max(sell, self._forecast_price(int(other.id), pid, tick) * mult) - profit = sell - buy - if profit > (0.0 if difficulty == "hard" else 0.5): - local_best = max(local_best, self._buy_unit_score(profit, sell, difficulty)) - if local_best <= 0.5: - continue - dist = self._distance_to_market(idx) - dist_penalty = {"easy": 160.0, "medium": 280.0, "hard": 320.0}.get(difficulty, 120.0) - load_cap = {"easy": 30.0, "medium": 30.0, "hard": 35.0}.get(difficulty, 30.0) - score = local_best * max(1.0, min(float(self.env.unit.free_capacity), load_cap)) - dist_penalty * dist - if best is None or score > best[0]: - best = (score, idx, local_best) - if best is None: - return None - return best[1], best[2] - - def _trade_profit_floor(self, difficulty: str) -> float: - return {"easy": 6.0, "medium": 10.0, "hard": 12.0}.get(difficulty, 10.0) - - def _min_free_before_sell(self, difficulty: str) -> int: - return {"easy": 2, "medium": 1, "hard": 1}.get(difficulty, 2) - - def _factory_tech(self, mask: np.ndarray, difficulty: str, current_time: float) -> int | None: - tech_until = {"easy": 0.90, "medium": 0.90, "hard": 0.55}.get(difficulty, 0.30) - if current_time > tech_until: - return None - priorities = { - "easy": (TECH_0 + 3, TECH_0 + 2, TECH_0 + 1, TECH_0 + 5, TECH_0 + 0), - "medium": (TECH_0 + 3, TECH_0 + 2, TECH_0 + 1, TECH_0 + 5, TECH_0 + 0, TECH_0 + 6), - "hard": (TECH_0 + 1, TECH_0 + 5, TECH_0 + 2, TECH_0 + 3, TECH_0 + 0), - }.get(difficulty, (TECH_0 + 3, TECH_0 + 2)) - for action in priorities: - if action < len(mask) and bool(mask[action]): - return action - return None + best_mid = mid + if best_mid is not None: + self._state = "GO_MKT" + self._set_goal(*self.mkts[best_mid], None) + return + + # ═══════════════════════════════════════════════════════════════════════ + # P11: 探索未知区域 + # ═══════════════════════════════════════════════════════════════════════ + ep = self._explore() + if ep: + self._state = "EXPLORE" + self._set_goal(*ep, None) + return - def _produce_action(self, mask: np.ndarray) -> int | None: - best: tuple[float, int] | None = None - mult = self._price_multiplier() - for action in PRODUCE_ACTIONS: - if action >= len(mask) or not bool(mask[action]): - continue - pid = action - PRODUCE_0 - value = max(float(m.get_price(pid, mult)) for m in self.env.markets) / max(1.0, float(RAW_COST[pid])) - if best is None or value > best[0]: - best = (value, action) - return None if best is None else best[1] - - def _resource_plan(self, mask: np.ndarray, difficulty: str, current_time: float) -> int | None: - if current_time > {"easy": 0.55, "medium": 0.62, "hard": 0.68}.get(difficulty, 0.60): - return None - if HARVEST < len(mask) and mask[HARVEST] and self.env.unit.free_capacity > 1: - return HARVEST - resources = [ - rp for rp in self.env.board.resource_points - if float(getattr(rp, "stock", 0.0)) > 1.0 - ] - if not resources or self.env.unit.free_capacity <= 2: - return None - rp = min(resources, key=lambda r: abs(int(r.x) - int(self.env.unit.x)) + abs(int(r.y) - int(self.env.unit.y))) - return self._move_to_adjacency(int(rp.x), int(rp.y), 2, mask) - - def _compute_center_plan(self, mask: np.ndarray) -> int | None: - if OCCUPY < len(mask) and bool(mask[OCCUPY]): - return OCCUPY - candidates = [cc for cc in self.env.board.compute_centers if not bool(cc.is_open)] - if not candidates: - return None - cc = min(candidates, key=lambda c: abs(c.x - self.env.unit.x) + abs(c.y - self.env.unit.y)) - return self._move_to_adjacency(cc.x, cc.y, 1, mask) + self._state = "IDLE" + self._goal = None - def _adjacent_market_id(self) -> int | None: - pos = self.env.board.nearest_market(self.env.unit.x, self.env.unit.y) - if pos is None: - return None - market = self.env.market_at(*pos) - return None if market is None else int(market.id) - - def _distance_to_market(self, market_id: int) -> int: - m = self.env.markets[market_id] - return max(0, abs(int(m.x) - int(self.env.unit.x)) + abs(int(m.y) - int(self.env.unit.y))) - - def _move_to_market(self, market_id: int, mask: np.ndarray) -> int | None: - market = self.env.markets[market_id] - return self._move_to_exact(int(market.x), int(market.y), mask) - - def _move_to_factory(self, mask: np.ndarray) -> int | None: - return self._move_to_exact(int(self.env.cfg.factory_x), int(self.env.cfg.factory_y), mask) - - def _move_to_adjacency(self, x: int, y: int, radius: int, mask: np.ndarray) -> int | None: - targets = set() - board = self.env.board - for i in range(board.H): - for j in range(board.W): - if abs(i - x) + abs(j - y) <= radius and board.is_passable(i, j): - targets.add((i, j)) - return self._bfs_first_action(targets, mask) - - def _move_to_exact(self, x: int, y: int, mask: np.ndarray) -> int | None: - return self._bfs_first_action({(x, y)}, mask) - - def _bfs_first_action(self, targets: set[tuple[int, int]], mask: np.ndarray) -> int | None: - start = (int(self.env.unit.x), int(self.env.unit.y)) - if start in targets: - return None - board = self.env.board - queue: list[tuple[int, int]] = [start] - parent: dict[tuple[int, int], tuple[tuple[int, int], int] | None] = {start: None} - head = 0 - while head < len(queue): - pos = queue[head] - head += 1 - for action, (dx, dy) in MOVE_DELTAS.items(): - nxt = (pos[0] + dx, pos[1] + dy) - if nxt in parent or not board.is_passable(nxt[0], nxt[1]): - continue - parent[nxt] = (pos, action) - if nxt in targets: - cur = nxt - first = action - while parent[cur] is not None: - prev, step_action = parent[cur] - if prev == start: - first = step_action - break - cur = prev - if first < len(mask) and bool(mask[first]): - return first - return None - queue.append(nxt) + def _which_market_adjacent(self): + """返回当前相邻的市场 id。""" + for mid, (mx, my) in self.mkts.items(): + if abs(self.x - mx) + abs(self.y - my) <= 1: + return mid return None - -class Agent(BaseAgent): - def __init__(self, env: Any, models: dict[str, Any] | None = None, use_models: bool = True): - super().__init__(env) - self.models = models or {} - self.use_models = bool(use_models) - self.router = DifficultyRouter(self.models) - self.safety = SafetyLayer(env) - self.pure = PureArbitrageController(env) - self.controllers = {name: HybridController() for name in DIFFICULTIES} - self.locked_difficulty: str | None = None - self.last_time = -1.0 - - def _maybe_reset_episode(self, obs: np.ndarray): - current_time = time_ratio(obs) - if current_time < self.last_time - 1e-6 or current_time <= 1e-8: - self.locked_difficulty = self.router.infer(obs) - self.pure.reset() - for controller in self.controllers.values(): - controller.reset() - elif self.locked_difficulty is None: - self.locked_difficulty = self.router.infer(obs) - self.last_time = current_time - - def get_action(self, observation: np.ndarray) -> int: - obs = np.asarray(observation, dtype=np.float32) - self._maybe_reset_episode(obs) - difficulty = self.locked_difficulty or self.router.infer(obs) - controller = self.controllers[difficulty] - self.pure.install_buy_policy(difficulty) - mask = self.safety.mask() - controller.observe(obs, difficulty) - - valid = self.safety.valid_indices(mask) - if len(valid) == 0: + # ═══════════════════════════════════════════════════════════════════════════ + # 主入口 + # ═══════════════════════════════════════════════════════════════════════════ + + def get_action(self, observation): + mask = self.env.action_masks() + + if self.mode == "rl" and self.policy_net is not None: + self._read_obs(observation) + self._check_stuck() + if self._busy(observation): + return WAIT + device = next(self.policy_net.parameters()).device + ot = torch.tensor(observation, dtype=torch.float32, device=device).unsqueeze(0) + mt = torch.tensor(mask, dtype=torch.bool, device=device).unsqueeze(0) + with torch.no_grad(): + return int(self.policy_net(ot, mt).argmax(dim=1).item()) + + # 规则模式 + valid = np.where(mask)[0] + self._read_obs(observation) + self._check_stuck() + + if self._busy(observation): return WAIT - primitive = self.pure.action(obs, mask, difficulty) - return self.safety.ensure_valid(primitive, mask, fallback=int(valid[0])) - - model = self.router.model_for(difficulty) if self.use_models else None - if model is None: - primitive = controller.expert_action(obs, mask, difficulty) - return self.safety.ensure_valid(primitive, mask, fallback=int(valid[0])) - - macro_action = FOLLOW_EXPERT - macro_action = self._predict_macro(model, controller, obs, mask, difficulty) - if controller.current_option is None: - controller.start_option(macro_action) - primitive = controller.primitive_for_macro(controller.current_option, obs, mask, difficulty) - if primitive < 0 or primitive >= len(mask) or not bool(mask[primitive]): - primitive = controller.expert_action(obs, mask, difficulty) - if controller.option_complete(controller.current_option, obs, primitive, difficulty): - controller.current_option = None - return self.safety.ensure_valid(primitive, mask, fallback=int(valid[0])) - - def _predict_macro(self, model: Any, controller: HybridController, obs: np.ndarray, mask: np.ndarray, difficulty: str) -> int: - macro_obs = controller.macro_observation(obs, mask, difficulty) - macro_mask = controller.macro_action_mask(obs, mask, difficulty) - try: - action, _ = model.predict(macro_obs, deterministic=True, action_masks=macro_mask) - action_int = int(action) - if 0 <= action_int < MACRO_ACTION_COUNT and macro_mask[action_int]: - if product_inventory(obs) <= 1e-6 and action_int in (WAIT_FOR_PRICE, ENDGAME_LIQUIDATE): - return FOLLOW_EXPERT - return action_int - except Exception: - self.router.drop_model(difficulty) - return FOLLOW_EXPERT - - def train(self, total_timesteps: int, **kwargs) -> dict[str, Any]: - return {"total_timesteps": int(total_timesteps), "trained": False} - - def save(self, path: str): - payload = self._metadata(models=[]) - path_obj = Path(path) - path_obj.parent.mkdir(parents=True, exist_ok=True) - with zipfile.ZipFile(path_obj, "w", compression=zipfile.ZIP_DEFLATED) as bundle: - bundle.writestr("metadata.json", json.dumps(payload, ensure_ascii=False, indent=2)) - - @staticmethod - def _metadata(models: list[str]) -> dict[str, Any]: - payload = { - "format": BUNDLE_FORMAT, - "selected_models": list(models), - } - if not models: - payload["note"] = "Missing difficulty models fall back to Expert." - return payload - - @staticmethod - def _load_maskable_ppo(model_path: Path) -> Any | None: - try: - from sb3_contrib import MaskablePPO - - model = MaskablePPO.load(model_path, device="auto") - if getattr(model.observation_space, "shape", None) == (MACRO_OBS_DIM,): - return model - except Exception: - return None - return None + # 只在非 busy 时学习障碍物 + self._learn_obs(mask) + + # ══ OCCUPY:最多占2个中心加速算力 ══ + if mask[OCCUPY] and len(self._occupied) < 2: + self._state = "OCCUPY" + self._set_goal(None, None, OCCUPY) + self._replan = False + self._goal_act = OCCUPY + + # 需要 replan? + if self._goal_act is not None: + if not mask[self._goal_act]: + # 动作不再可用 + key = None + for k, v in TECH_KEY_TO_ID.items(): + if v == self._goal_act: + key = k + break + if key: + self._tech_attempted[key] = self._tech_attempted.get(key, 0) + 1 + self._plan(observation, mask) + elif self._replan or self._goal is None: + self._plan(observation, mask) + elif self._goal is not None and (self.x, self.y) == self._goal: + self._plan(observation, mask) + + # 执行动作 + if self._goal_act is not None and mask[self._goal_act]: + a = self._goal_act + self._goal_act = None + self._replan = True + elif self._goal is not None: + a = self._move_to(mask) + if a is None: + if (self.x, self.y) == self._goal: + # 到达目标但没本地动作 → replan + pass + self._goal = None + self._replan = True + a = (list(set(valid) & MOVE_SET) or [WAIT])[0] + else: + # 无目标,尝试移动或等待 + a = (list(set(valid) & MOVE_SET) or [WAIT])[0] + + if a is None: + a = WAIT + self._cells.add((self.x, self.y)) + return a + + # ═══════════════════════════════════════════════════════════════════════════ + # 训练 + 持久化 + # ═══════════════════════════════════════════════════════════════════════════ + + def train(self, total_timesteps=50000, save_dir="submission/", eval_freq=4096, **kwargs): + os.makedirs(save_dir, exist_ok=True) + scores = [] + best = -float("inf") + obs = self.reset() + for t in range(total_timesteps): + a = self.get_action(obs) + obs, r, term, trunc, info = self.step(a) + if term or trunc: + scores.append(info.get("score", 0)) + obs = self.reset() + if (t + 1) % eval_freq == 0 and len(scores) >= 3: + m = np.mean(scores[-3:]) + if m > best: + best = m + self.save(os.path.join(save_dir, "model_best.pt")) + self.save(os.path.join(save_dir, "model_final.pt")) + return {"total_timesteps": total_timesteps, "episodes": len(scores), + "mean_score_last10": np.mean(scores[-10:]) if scores else 0, + "best_mean_score": best} + + def save(self, path): + d = {"mode": self.mode} + if self.policy_net is not None: + d["policy_net"] = self.policy_net.state_dict() + torch.save(d, path) @classmethod - def load(cls, path: str, env: Any) -> "Agent": - models: dict[str, Any] = {} - path_obj = Path(path) - if path_obj.exists() and zipfile.is_zipfile(path_obj): - try: - with zipfile.ZipFile(path_obj, "r") as bundle: - names = set(bundle.namelist()) - bundle_members = {f"{difficulty}_model.zip" for difficulty in DIFFICULTIES} - if names & bundle_members: - with tempfile.TemporaryDirectory() as tmp: - tmp_dir = Path(tmp) - for difficulty in DIFFICULTIES: - member = f"{difficulty}_model.zip" - if member not in names: - continue - out_path = tmp_dir / member - out_path.write_bytes(bundle.read(member)) - model = cls._load_maskable_ppo(out_path) - if model is not None: - models[difficulty] = model - elif path_obj.suffix == ".zip": - model = cls._load_maskable_ppo(path_obj) - if model is not None: - models = {difficulty: model for difficulty in DIFFICULTIES} - except Exception: - models = {} - elif path_obj.exists() and path_obj.suffix == ".zip": - model = cls._load_maskable_ppo(path_obj) - if model is not None: - models = {difficulty: model for difficulty in DIFFICULTIES} - return cls(env=env, models=models, use_models=bool(models)) + def load(cls, path, env): + d = torch.load(path, map_location="cpu", weights_only=False) + a = cls(env, mode=d.get("mode", "rule")) + if "policy_net" in d: + a.policy_net = PolicyNet() + a.policy_net.load_state_dict(d["policy_net"]) + a.policy_net.eval() + a.policy_net.to("cuda" if torch.cuda.is_available() else "cpu") + a.mode = "rl" + return a diff --git a/logic/pve/submission/model.pt b/logic/pve/submission/model.pt index da3cc09fb2de9bc5754f7c05444a81c9db970fa2..7b1fa412a438154e6c868792244e701e5b9a7de4 100644 GIT binary patch literal 1249 zcmWIWW@cev;NW1u0DKH047vF!sX6*7i6x181=%@nP67;3XrO_qwvZtLXarboAtRVs zRGO1o$W*Ks;LXmVGTHOJEKnMR18`a<%Af$XOfN0JC^xYrzAUwCU=xWJeTWcS5+>7j)EFT-F0ivUoP(l1Ue$^^zhRbmM+qT@4D+?)(Zc8Y)h7diQfqUrHj#Fj6hLDac8HAH|d) zVAg;*1fKNJH6zC%FN)@CaLv#(gRT`hU}aFW1_1*Z8UR?MJiwccO$Vw&j#(G37nF!W n07kcivNjO>07n`q`qoMN3N_~>20jQ_vaGb)5!)U3SW{2|(ZOE>TH6>~2x@+!Zw zA#$c-a+%I^Pp(b1e?NZV_LaH*+ac}Bx_}j7r{@0UtmiT{JgoZEddGnsHUYKLZQt1g lycwB97;rlb=r%BDU<6Sp&J6HoWdjK^0--gKo(|$L004F+N>Ts- diff --git a/logic/pve/tests/test_official_evaluator_rules.py b/logic/pve/tests/test_official_evaluator_rules.py index e44aa743..e36041bd 100644 --- a/logic/pve/tests/test_official_evaluator_rules.py +++ b/logic/pve/tests/test_official_evaluator_rules.py @@ -21,11 +21,13 @@ def test_agent_source_allows_documented_env_methods(tmp_path): agent_file = _write_agent( tmp_path, """ +from GameLogic import Action, N_ACTIONS from RLInterfaces import BaseAgent class Agent(BaseAgent): def get_action(self, obs): mask = self.env.action_masks() + assert N_ACTIONS > int(Action.WAIT) return int(mask.argmax()) def train(self, total_timesteps, **kwargs): diff --git a/models/test/ppo_thuai9_best.zip b/models/test/ppo_thuai9_best.zip new file mode 100644 index 0000000000000000000000000000000000000000..36e630f13125ae52707770632766bea35ae3a9df GIT binary patch literal 277955 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

?7xeJHB*^LELQKnEQynuSTwFbZ zzvW>x`DAm83YQy@-~=tW==z3!`8#A_$d{zx37k+Pw7t4-0G|V~* zAuD?0pk~{MuVyEv`cN<~KJ|$a3|oqNPd78;RW->4-BA40pb1@V7)l1dY(zfn`p6cy zpUG5r*+EMu>SK_sIoY+VoT}%HL;JD_vS;HfW?<$;vblpAeb_w}Pc#}$&$B_8MJLi0 zx7}FIec$2v7cEle+>#Va+CT_xOVp2_0H?QxoXv3}?RNM>Gl#ik z$ej74aNaujq+*YwzF(wA8w@9t*S%t=PU%SvZ|q|DEvG}%le6UZNvTXy@mh8qX$fXc z7}_@76W!Jez#_>U=gl!@^IANGDJwhR+QRoR)sDdRE#Y*@p&RUgx2vFR=su==L}#on z9Yh+7$ADIeB|hDGf<5T74&93}hp`=1JnQm$oN= z`U?$APKd!nMXhj#MY>#;rHbE=Ey6xW-+^IS9Q1j56!JeTV^4-?QN#Dz{E_REiCeZ2 z%?z+6-b0_m$)s>1-XX;0_v~2f^adDlcMYu`U4Td0hd|W3cW`@8UkDMqkaGpYS@VyR zN$cG$8Miz=a-zQ_oz_(YGJ`!x70hRMw$CELDRaon&&6PDahA4mZAfky@W`dA7+5On zj@#CpWqOZ_grR&B^gFZ`s;gI?b-bzFtK*MdcA&ptBfuzw%&B zUBH@9E8S#p6ucU_}JU@74zUUL8W0w-(~v^JX+KK8;KoU5GZ#6X5F|P10H22iLWC zs0i!djofN=iT2}s)GhHgcG<<bePURr(yv*2%#cQ=E)VFyCEW<%&Vcr%?J z_=IMS+QSdBYe|P`+LQPdA$Wc2O^7$_pF&tN*t>k-3l9$W~MMA!KxyZ13|y54~) zXV=q7OHFa^R$qGfNEd86;S(I}7t8v5ECttqLBx1&PaMpcL95IV@@8{u9M<6;P1%x7 zM^B&PaIMS}lkTmh>%M(r4t>^zHoBeYe4}JCr%?!o zf+wy^Hl77dX+}_0` z|5$T4y1Or9(uWZ8ITYL;xDoRN*k^+$32}7)ApOIP`7Y3$XB>y z6zfdh_gCNLanm3CEt;Y4^JgF*?*bC*+4#I4vKd(#_}CXXuB+022(R(|J(_=!`ptLT^%trOp`=}+F(|PdD^(xxgFv*4wrHCbMLmv*=kj-`hC znPXE{VXK|Z@!a|+tYBqtlGH*DF|T>RuIr0WU#sJTCHLgt#UJSUqUKoKo2A|2kAv2v z2GFm)1|*0-ti!#fd}*m2-XE}@{nXe6=Tt}2C+C)s zPLrNMt9jE&k-0r7an_)VmfoR;w{7uMj2^bmV2Jh&5vYBfN|s$&h5c5XrSsaHL1|wn zTySY0+^assUpFy}Mko6*D}5qJ=1V!;?ADE$IrIdTwlAhbERxB|FP%Z(K@TtW>VW=U z6#BeAPY)k0CJpU2(P3vU&{+b1c(fu4Ct5gAkJz=a(CsF~e_jU$l@hX3J`OT%B=E+c z!VJMW8fr8bDnrvqLkoSf$LJFjJIo-DMk6gBe1T3G`kqn!dJT?0X+WQxVMyj!1dAb$ z;BZJGDd=v<>S%tXsuAO$L5VfAVvWdNCSgQ@yMN0qUn5` zF7ITDFXY2v)%&}UEUF;ijxNO5;TqIBSskkkY_Z+Vd3>JM2ljh|6;x%$8To+r7oe)D zD}9~O2tAj6Wu8vxLzbzzfnm#J7;&W&H1HP!oz@zg_)meZ<%4nJ=O*;=PDj$>nRnr9i>?O7vIea9P9%rCQ7HXMQ{lYFt? z(TU7sy&!V(UK^~O{srPMbj78K3(1Iu=5*5D73jH%r7A_G;Om<$K~`VpDWKK4|29v<(l ziCcExqa7P);Y*tntYlIkX>;Q2&W~Lj(5ux(;%1)%K680wv55^Ce19sPdo>kYI#0!c zdZV%1lYw;f(w_Kbg$TYI8_~`M+IV`H8x0wbP7Y1B@ z&bqs2!SIYdV+LY}PD#fIg2q)IOlHD(ksvioC5(p)W)ZRC!^TUs!6b~P-+ zF0^Qx8m(wIfw}pDNA{dwgd;BEC<|ao+NZKT6$+y09~Gp6Wqp>@tMi z(<={bLd1B=HVK`Fr_*KZwbJ>R9A zx#snVt=eOV5g!VO=B`a}Y0Er(b7dSHi?JkaPl(8~XP&fCQ)Be-xCi|j&!qk5%z-(T zL(uSB3ZqlWuvvZrY?-nFKfato{k|>32+bq(;$cTHIPF8c7axT=t6M`k^k64`dIK8{ zJqPd_NXECbr1uV;q}ex`;HZdcn3mTVyXQZk-X1+j`lwhO-` z3sB$K5p@sVX09yVN+%k{k~BvjY+=>}!FnpO-+BN(lr(0e_@f*=lE#n`1#_{Jl`(!& zEvMUVcoQAo0T^m|7dEJ*;jQ>ir219`4V%qFz4_kQLiH?c-aA*Wmg`J+va8@t>VA^6 z?HGTjogAM(mNOmGchF-e_hWOFwT#LA2Q>1_K_)KBtitJx7bLdaRB?3B z=%s>l{5g)Dp0(N?~T)f{^jc1yf)0)IS2S$|}9Wc8)_ zuT?SJhoYwD6UH*bi1h7ihC?Ruu-R}+%x*S`4Dh>6v-beW>f4V@QFDdf=eomz4L*d8 zw1T+R;XwMJkB&c8(9A8kuj?|4s;S!c?9i>lQN{&^mpI1e%w;4za!gNTCb{S)l)1KYx zr$u+EZ>R1JrVy)qE~Vt$7-!pb!|pM?sM{zV!kcPI%KCM|(T74X@*}1YOngskW3lA`rsL@)q}RShV0g4U8BqL`2D1m` z292}9JaIMlYO29}@5ewBr+t)7>qeV-YLoAyO{mD(m2|Zl2m@E|mtP(-iL@EIsbW=u z6NxZ$!)GZ^X{c2n7@XS>v^LFx6;6(9v!Xs|*;Ee;LmM)q`hEw2&LAi*N+L_NU&H;1 zHe|SQD9Usu(D>6$NdV6Pudf_}%^zN%QjM?F=CcozJ!&q7O$OW;ahZBfvmzU!Rx$?; zF99>B>9lgQJ-#0qz(ysz68F1Sa7D6{5#66dmb^qZnwDSAuwE}1yj6%S3`gp(zcQF~q!vR!>TeI7Rh=S;XuyE`6)xl1+R zf%`fTeA1Msojs2Zi@e#f?RwHZ+Uw|(nWosNauNBEa+}TSvJMX9Nx*8R1ntf)!P(b6 z@Y98RV3|+^7baFhi(_iE$%eb2q8mz*Qh8*u)jZ5#`;#q9Yv|ry#`2rEV*4Q%z@%t9 zWGtUVSC);1p+#S**Mjl*)Oro^e{`L0dV7~9EiI;P+byGyW^0h@NB3Zc)nV#$xQOlx zTE@Ti!W~yhKJZO!TcJEQ4K|-z1h=iak}DG~LCz6A-L=~nOZ2DED@+S4xupxQyRL$A zK0!hHLewzZz?yyTPQsq6kxp(aNyF10p*`$pXT7&1hH>gJcT7G#*wqNuJW0ai@>y)W znLFN{vzVE+uP5F=HWQ2nwIHh>Sdg(B88TB}6PGr+O+!}iLjA7{+%uX*$LDIG+N&*W z@r5z;=;Em~30JG>gI3F^@#iEiPm@VT3bw=OW;0M{nhk1}mSB~n40xx8Lu<#?w0!tz)a?2c z+=7kC3@|3|i=xply9b(`X-P8M8IXOD$y^^^P3JHxNN_=GtmxW_JhE?y%cJzsT*m-o zQ_b+Dwi)tr)#3Juj@URm4I&z?uXv>4OZo1!BNMD@-+>44%U*$on`AeCra7&h{zt)np)4pBhR6v(M80kJ50@ zbTeEN(SU-;GZe=-~>wg$}Zhip|2YrR9-Ae4MpL&v4jaHGh{Cq|Y z#N_Uo>StX6Z%0Y_^UhIG~`3>>9q%}Sl1JO=D2>QzNN1H)E*lX?lE6p~FLMDNcS8g2@B6;GuK3>D294S!clt{BR}!+wD6K^KMcIUZT$G zb=60soDf#BS{sEQv+2uO#pvKUh0SmATwZdnFTP3(WM0c#quIm)u%8%5rWX#O6HF%3 zwI^P~*L6uazt9opU5&%XT+FdBcLDUxcg2%qPQm5U32gZ)SJFmL16lWU?A?4Y<_#Ci z``sFhCRwYY-#SC=#l=&zb~J;%dhxjNww~Nx-iu_q9)fF|Q<$0KfG%n}g{@rF1zN~V z$%9W8IG|z{>&fNSx}Lg9uWeYudX=lu{N@p)C{v4^{B)b$y(P@<((GH1^yn+Sme?M( z23UYjqbGPGRZc2eaCbB@J#pLiYT6*Wj2xR8M+Y}=O@c#BpmM@2qP}Y;`Ue-o?#T6Q z!oGAe`NL&u)NK)rzwnsqmjSvQ=!!Zo*MWBWEKKq%bP&YwNHcLcjq(e{Q=Kzu(CV(_ z%#M6&(|b6>e6)vkcY4u}eJtT>pN6ER&sq}MX$W0BKZd$)s$f=Mnn)sbPcnlI_tJ7} zU<_w(hR}u1FxMiEZm(F62VaHa8>2qd`-wKtWim4Ju`6!KO2sER14!ASAV&MKKB@NB zVv0O$vDx(^X0qyC>aYKtojm(Ad}uojjrk&GYw03tJKqgoKG;O%(Q0VyF%`OcE(GVu zH}Y|r&T{XRL7??s3ko)OMxA~OA*pK?>2+=f)zw}~m*gLTPttKDEw-3?z3xQf=4)Yi z55VDMDGV`L!kBjTCh40-(M?M>Fhg?2g5j5FT4pGNE}Q$3PtmUY^TvTBtIrFt2z4c& z`*b2bHEqeBwEd(puBO4w-&APD$3pwFP5VwTYeK#YwPDf91Dw2jJ5n7{y!9PyU+GScDQH`?pybr@CX3wkSB$meY90Zo#7 zV#z`svX8%woOIDfm-puEi5uVf>%Yt3)wclpVy!&{epv+0b8~Q8WfRy-mxeAEd{3or6-I2gsWj@%2Ra>5|RY9OAwWrn~0Zq|~ z9Bgd^-(LBk_@E9(Cr`jD2lP;qGl_&PE2f{#JV{mF5K?L!PewFT#o-6$(1fFlA!tb` znXFz-6G!@yG>34QujYYnHvKSZWH&4rKZae^QjKx>@}72BF#+?18|k6tpDA4~BQGP5 zareTP*%|&pc=qZF{@tRN)Gul#_50ovk7bV{O@=L?CZ`<9TboSMq!ACzdVZm^+Bsw8 zqb%r+1%!E}N@Aj(ux?k@vd;^KU@%_`TTgMIWmOF^hzW#AcT0(%p()igyG3KCb9daA zI^*cLCTM)^6lKR6lk}=gGJBLISu{0R-*$bHaAXs{{M4CvHf#nXKKc>;XbWf) z+>AV*`h?YZ*Ad-~eCf)N^K59-4K&o{1!EgOgjkv11naz5ynkghTl#`K&#f$>0jsAl zokJ*=Ow}eA92TaDDVpT;<&a+Q%(m4v#K!xO_H(Xv~^QcB`g9LFH}Gdh1Qz z-PR`}>lI9f?^WvhtrZRF>Q76rmY{n43;u$ApJ@*lCw3*%ovJx%kphQJ;HSO@i(_{Y zVGDcGhPvC2$J=M-(P6VTLE8Jhv~XSyIcIs5 zN!#Mh#*K}Iru|!i<@3F8XUH^Alip{}Ph3DE(yEy7p5tJ~wwXkCMKU>5rc2&`GDoR& zExbFviY9wckVk$VWbe5g=;QmQVBBgZe16iDuDm;%b{%L>rgHbkWyW(!>82#w>s=!< zO{JVHvX7>3MNTxN=CrrNW`g(3)YE!6(@~XeF>x;}paW?00ez{1N4H7}I3%!$XzbWPkIst24sUzFyJ&Z+WvWf`t29WP zHPi5o{!-fKL0=4rP)F~}R?NV&{joUt3LWY)gHC?Cl{l46=byb&Njo3apz?zZJ!V!0 zr6Z=Xv0oidcNmQ*w}G7nBOnOCUaxRYU7-pMzYED$;ShX=8eU)M^Xhg$aTlCca7euNy)nT&>WKGiHf%ciZB;fS{fnf>#EQN2MI zG@32NGu3aPe5@<8?on5Au#U@szxGD;i#BvZH+PcX z@eXM3(IiQo#?VfY*J!0{0cyDR!ODu3q_B4mGFjyyJ2{?AAEkpsR=$EO)B9oYJs)B< zqYqo1WN5$RTRGZ>&u3RHyo8rRU1;Z7A8Aa?QhIx<2?m@P3|FJfL2~W^|NMty;2*PM zwJh49D3X#-c|3AHuQlvDFcGq^rIJm-4mgNk3gg?#K&AREdvc^HX6mY7k*+4HFNp-N zj52zB$si(nGXOQ)+LNfNR=Dh=3La1^Ag@N6z&_}VGhKR;fH{X?{5TCvdu{?>hYiKa z^Ul-P3oOa0!&018G?A&CQOu6^dkFKRwoQ zqr2m7K!rm|1sT+c^(}K^KJyF6^IJt^TgVI=?RFISC-U%+e>{JPYy$Lcw}Hm&Ex~pl zM?ti>lDRi02IpHhAZ~XG$ho*}M9bBW{rXs)IHZ091A}HLdTc}C;wZeHD$I{d9 zZqvkVmtg67Yp_2uinhOf4kno$V{-)h^jYL?x_?*+F_k^w%ib5zP}@1|tJ?xh$#*4c z`oV1Fr-!usSut%@hF{I}@I1xIjlpb5soa%PzOLAZYncL9_#oU?6LhU`y zdY(i=CbYt*p~o2Qi(JaGDxVDGd`WI6E1dZ1E6b)9;&9D=`0WNES_U)e_f2xf=E7iN z*Ptz!w_FF)b|=ujF>Od(w~N$ckQSM%?+WL{eQ{600$hJzKq3x@z~?Sq$TFL8dB&X()ZxP4oq$WD}bX5Z`2Q!Tp={3YYD>|T^erLFSFO8Uu z4=2v4&%k|%H7RI6orb2E5k0@AM1NrQDX=G3CJ9eu1IC$A@D2Tb*iAT4*v1&AT*4^}gwVRN~vUE3{x-fz)DLYJk zw{!=+PM%nFpo-j+o@SR{)5oC(1IQ&89Z-EzLGS77;IrHuTG-H!&OW1tBYKHx-|ro< z^=egUXBdQ~)f-_)nicFC>IX@#MdU)3Dm&p&8)&rd1r&`s44tp?aCxWIM7699zB6L5 z`GWRjvt<+VI_DyYUzbCJ0ACV+U;(a?zM)qQBIp}m9awWioAi1zk60hh=T~0W!jYrf zVQhz`ko9s5q4wjcyLTJ7xA+CSe{cuX{1%O++s0D4xH}1d=ELoCH3EjFINc_S`rdd= z#g!jPTr)koc5qt~xmCu0wMq>;!BF|yF6H#a=PNYbW*!aRtVd&1W;3+?Xu5Fw0l6TN zkilohL8-nK6tvzCOD)!en$ZnhN?KEX=1?$mky6{X1$f%I1@7k_kwmSk5MzBU;d+CmG(gLbY`K++z8!ACiWlbixkW3I(ny!ej;qksU(drDu_euU zWq>7nkISPz&%j;xQ|T-93HUHnbm8hUtkU!*e*9ka$jMIZio6D7 z@QBs8(b<^HYIG1rdQYbZmd4^t?_&DAat)nUUILrdQe&oKMn<^6Wh+G`ip zJ3NV8b}pyl+Zx#Bx<2Xn_6E3!KGNp~pXkBed+4Akn~-)l!mYmBN#OVI^kmEtC^H|9 z_jL}@XS$~Bk*i#-*ZiK;w$~DfKXHr>>_3$bPHsfLWLLvp-4GJk7 zu9nsJ9ew(IIoKDD$F*9Ns-Ds(hJKtKSYyh%@7_q$x-<7f87Q&s>Bd}n(j2_)v1WO!{+!5GQhkmo^q+^euypNDS$HE6U%EOIyDjsvve^kX{(Tc@>NlL0yJ)d=aWrE!_#z#c*#b9c zda=h3mg3!|EVUl8Qm%HDi@RGBv~lRkMue;^-@W1`bZ9(J{!+t%zPMmVR)sc0*B}w} z?tc?@SuSC`US8$%a1rG684J1C(z! z4m|sK;;YX_= z4S#x{niJ1m%gIGuOA@yKHQSNVpwWi9M0Cg$o1Zr%UL}Lb@fD-Ux67{Nna3>1uI_-B z7x%>YC%U-YzK{g(YYO3=37+iN2**~;g~BGs=~#9NiTiGdA1|vj3{Ilz&yRx9IZJX^ z{TO-P${rUtSxj6VlZkp%1T|(m5$V%Ls1iLF3}a?f`QhGV?FR<$w3z|yRSEcFH3+Vi zp#H4|^m6r9D!y-thvfEnWRe;>e;);pZXSmCt=8DvXBTx?PVh*ZQrI2X0)m3H&|^>) z857Wz9a*A|V{VQDjf?h#30zF+ZfDRDzM}nCEvKI)Gcl!j8}&Yg%;pQ@>C_eKkU4)5 zz567J6qRJ){jT@u-CSoFo!^+m<}3tRac|tb=QQPwT|ytOa3C)RjzBkgV>07lbG(xF zlDh2chm+afFmt3U?RMb`bL#?EBl7J$sE^HO<-YB(@=!V5kXuOFbh$^RvY|L~YHw^2 zbsTxiJn6_mg>;=N(2cLENc-X`wCAi2IL@~k!bM$}2Vov$*^>Em*-S4|y4DsFxf)qf z)?wOY^hDxjR7R&A5i?(X3&GOanF3FToZNOBtZw%pZ)9d@>E0Zf>MRhN2g<)(nMl_i zFhuWmQ$fH^#A@nEv^=@{lYMeBcl-@7E1ycA)BlIE^Ni=}5C6Y1LqtSmWQ0Ve zl6=l}k&$*r_*O=H?=++#D~g1YSxG~Y(&lrnDBKv^i96#@=ISn`d7A4_1K(1y(6a`d?Vjps6cwBc9FC1crhSb5%)ie zlJtBdF`~l=-mmkOGXCVk1rrikdm7yQJDFWW!ZB6cjI*=6aeHkD2U-Vn;pL6!Id3x0 zxU`Y(j2tVoF6@V=9$WFVkJ`L6(o|^ZrjOjWj?arcoBCj2N7$#Yt7Jgh)=Qp7q z+{>x~l=bw%Q{^r#u+Ze1OK#|Q>^YS7O2-c8%3zYShnPDo9_FU*LARVZUL0ACACAQe z_30IO!)**j8@~gkSM{X**cZwY9>S*GS@7FvBRrJmr6{}8ByQMAUa^vYli`Y4x;gTw z4NkIXuW7Jf*vhjHOySWhEn$PcGB(snd&3$xelWs~*L1%kRt_4^D__O&h`dcaPklWq z)rPTR>la#a{V=>fUI^_0Z-fYAb$T{@Kt<$!4Rk2i#woTlDcv>~8h`fYo~PRA!oMrv zaO^ZjC$|W*hdzY<9ZOtCE!+d|gMeF}cH`Ys1v!4pr+6nn{5o|B%)jx1qF0}%FIXmu zg`+r4X^*fu=dNr?%0~7YqXun#RLD&!7RG&^hYPcA!h83v!ll_s)V=*Z^ro4dTz89> zblMEizKB!SnqjDd4qFCvpw~TaK|zf@Yr1^}^~OZ*w9*$JF;{ zkAqYFaJp+K_cySWx&$sQbF4K&Tz4WWlby7tY1N6a08 zv1^8)NmDDd|7VWVEwbUx)1BzK&JMFI=kfj-n!J903Y*?I&I_W};Hw?|#A!a;DX4HV zrImN$l;K^l>$^xWf9fn7q^^ZpBS-Q5oSXFL);5~BxtW5TuY=h>C4N;iR@Uj`2wGC7 zi~iSb(E8k1))*d%jk}6ThWBaJ(M_yXYz&pB@54{2qjPr3e&|;C8Cq=HL|uz2sFWX} z7~jrl;9UUa_4h@WM_YMx1>L*7fghud1`#FTO8gS9gAkSJM!~Eo%s8)?!0s0C@PEVPs(qX;t5g* zr>-?*bzBeo9i0IM1~=uI9)P_XhTxZX*4*h|Gh~}3^Ynrz5aWIooX2&*0kciS)KW(@ z?06HFT}bD7A=w~ozX<=06wrO#A<%Bn5vaNbdK6C)>q87_PLdi=G_RoEVb`dy<0Cj7 zb6UWWR_IVQf&(w7!SsN!q`ay~biS*=)rMM}5?v2do{z+|)^w`%+z-DF4Z{Je##8gV zp6JzI!~*(TUa{YdrdAvfs~?_#ZAV99W3LBb_jwBsu311cdK;j6o3ZdFTZf-|~Jx-DF@Rphyj&q>1P(a%0( zIPZ`eD%;MZhlje5pW$KjSQ;Zc^}-J{zK<85Y^>y+Q#HWn`~-FjmReKOwDH=VOg=a^ zip#s5L9ZK6!9PY>Y}I$c*WY8Iag~plzcT~YugJubz@8}oRe)2xf)UQY67O76g8DZi zh`wb|Hy*I3jZf1s1J+DJy*$D}-J@OfTl|f##@D z_<3KAtf3(dQWSt&J%9~IX3)y!BDDB;5*M`@gU&l8j`=hkuFNnHBGwj*X~vzU%#c2p zN`B&Sy&!zmZ#yk(x(j`)d$Pf*EdKgz2N!%lKn0m2(6{9by4cKPwXMA|M7IlHKR*wC zWbcAb;bs_Q1XOa?jYl^oiMG!=;PCOyFm=5vXL%U#=5TfP`I=A9_id!xn)%Yq9Szqu z<_OO$Gx>_nZt6V27>zCli-yKWAS!bTnEjDFd^=@c_uvBwZCAuWPLsIKOPMD|NPg1t zx47N(h4^4P18w;u*Lc1OE_)lGN#QuT_o5WJV|xO;oVypl3`=L7@kfM7(Hh)Y*e(pQ z)?hbD1AlSy15hH49!vG2+H9GiZ9v zN|=0eCR=qI!2g;46KZTXpgc8##V;~^-{&DD_%G(i*o6+x@DrxqT7~-+hVc-k61rn= zCU;fz6%GIU1}{`QiL;M?0V@9k^)N~ z+^|GUoA{c1uh)v#t@qQxi2;It?|IPAWf?c7l|#^QQ;OC0hRcg0ChlTl_n_$t3)BHDCRjfL%D}PWv z1R~Sa>6MD4xyS18?L%rjI_m(QZ+!;#Myo-7)RdnnX|Q;?TG;#79M=CA$?cY>ATLE7 zA3a|x+tRs;V)>b16Ehxmj84SP(!BJpk2<=ID*$1rH!f4Jg4JmcMHAa;I3(?|FfZ4Z z&3<1MClqzUyJ6KbAN5SU>|qCZ-Pd))gUiC4;sv~MgrD%HvKFoz?Wb1<)#Z7okW4@zJ0n9~hCu|k?vVm$iu#(=A0#Pl$9|ItpiVg)Cj_MxyXc|yz#Td9-qhf3=k zVZaOE$@||6HM;|4mo{eM+RN#3>+EO3`6IQ|U$GDO6-V)zKgBR0b2V2lo5q^Bg+-%S z;bCPhHMKO0ovp{Rmqk12AGZJvh52l;?<|Zhj-vOym!a|KGB`JNf>8ck6JM7W3faC! zJZPT*mK|xK>lIqKZhJfrEuRS~Z!%%LFq!Mi1_&2>h%i72=+MSMdaRhhE?3=fk(aaZ z3HP4rqJyOH;+Y0zSPM`r^j$A!{6ze28!}~gA_$TRaf490qwRlW4TQ-XI=cn); z{W%!EOU5OkOL65Z8=n8e3|~1G^Xk$^;)tFNqTapjyx3Hgryp3ro1k+=Y|>WPcc44^ z`{uLIu`iF6JkN7S-NCIONc!Ct^;enmfm`pu;B$uX!1f=Uw&^ZjJJ2qMtn;RJ{tJh{ znc%nV(}L!zayoe%`AXz|`1!69(w1$5>`XiU`DCwrkxDysTcXF2O9p_mPX@1f<3~Fb ze7Lo)3!A@G#U*>5QoXe2&h*Vh`L>n(-Dy2ezZ%V{zG>9!On)&T+=(alErv7C0=V^C znRq>Q19@HjMQhUnDgUP%2j9I;dS3!@tZ!E#f686#IHb7TE!u#qi|)e&o5SMV#YJ4( z;=$F^c0rFTU#K{`AN6=FeeNRPk-x<+;mRdXR+aWp{eb?|qh~kq#ETx{jFb{#L+wdn z@m+mdJv*EPC3PBVQ%f5XZ-CYiU9_)phEC_N)1b6@Fy^8*Ej^e`&&FI6%nwQWRgMoY zS=*g^i$AC=)s$D6{h+5)%HW><9UK*vPbER|T$}zFLe(l{UW2swMX(iKN*cmjzfZ)h zMrY(}2157Hv$S*DLePBQ3XN}5usHYxe0VxZp0H?|uy(o;-7h@=I*!X>)uFL;`>!?D zp6etmU06yM{WFA@V{+)i&}=?wrp7zMZ@~l2M<7&)@N$`vlzT8?qv^-V)-o5JY(7!$ znOMm0dj^B&Jf_JXbNG44SnN66A8S)av%6Y6HY;|)zQaSre%rJ0^X75fRb@8&jvfd) z9d|>t@j+I3@ffu7W2q{rf!uRPQD@T{82NZ3YF`h<5zju-M)@GLFP#qyW4{C6O^~I} ziDGGx6E3c}PC?CG<%<*FL7(j59CLC5&Fa687x5@`^*;o2C&iO@{uwMtJSHr0O%~M- zJE7$P6YRROfLDE}5d!U9P`)dfx>P2RLd|UOD_9AeyLRN)MyGjKnL5938Of9SDx=@{ zMBaC7ARNhG$fxBkWH=-mwQb79p^kd^zSa}It$s?uZe?P>Q&PXLOEy)6RKom~CuyV0 zalz-paar!7EL@j!55_+>D((~q)k7?am+!?BUG-^~-*LRTMTaW2 z$D!(^YO;1*i|zNS=yZDz&abzGF3w-YXHgB%>#;FkofpN&G>E?{nQ+^}bwYLbeoyd7fPwlj37w;39RE5mY)8rmIGMGktq#Z^~M;!=ZSw7cVcYRG&A zOV%0Ct(RxvfL9jJh&SZR_g3&^oAtcnDRNVVE?S@31p_ZHL8DRHIC5nVzP`4P*rQPq z(pHbhww?OC`n56jc^W_k`aam*usdmXt0m*WI&l5q$2TV5q^Zfki)Sg~kOkMN_}gmw zFE<{7zepXO-V6B0>KKL|2dH~b4eqkE4TAc8rO6sGn1*wBa$jRIH~SBz=Nsl9mNd;? zy(!9S0^U=52m5y=3(D#pXq1r?XVhMyj@h2Vnvh#C_{b)7tk%HdmP)9*@EqzYqsS&q z6Wi9U5s&}37p5-`L7`BMBaYPL4A**SO0R~}Q4?Us{5%NOPvg0t@5;8#vu78DUaVLY zNXKrhK=sSzbT$1Gs5sw%9Zgpud*WU3ZnhEbmERCEqU@JKyvLQ81yt0 zr;M}W`#q=Nr6FUXBr}`hibFZ=Eb?C`W!Nm`B%j(OaQGc%n6X zHFq2b?8&8B8J@i3k}m(XT!MDp0{DRp(Mwx^_!B1h=B%!$n4*KxA@5;TQ!iAuoCnGF z@$hWG388iCbn(oSM1G^53qEPnILyPC7C!waYx2$F-fqUMw9^kq6nY5j5<@U|vj|*MGi(kLD$CORuXh1>`l{QZ0roG$n)6H?P?`s0Q*rCHyZ~lgwwb~$?`kEB{ zHd5Z?arj#D8)mm0fu;#D`0f`zAhvlp zyUM>Q;;yb1aQRRk&s{kk%_HXH9E(l(LO+I=jWfcK;A}b^unaYQdV#ooG`BiszzxHP zG}rtXn0@L`_h;0KAyLo)-Z*9U-8%}sE3pX+5`f=74IBZg=KsG;hDL8v1Pd> z8uSGrC|Fl+t~3v}_M9&8$d1@GKrZl4foCP}BHgFa>|L-JmDfy>^odsar2gGetGW}EAGKxo?WD2D%CJmbq&ue>kaLmAB4on z4X`MpJMVGngL}^!p!u!Z3QjfZH8tFwe;R%A`R&lgI|kmDXDrU7oIGq_cJOX(5ei^Kd+DJ9Rx z;)g0-R(-n@rmxBeohScc$<`{-=vun4t1U|?jaB4P?pp!Xeb{2ha!MTN0Y*-Vn6@^A zhNhNKfjv2`qV=C=f^^=j~;Z+x8x_|yI{-d8qD1p3o=`8QDJSAxb6E? zPSm^x*-MO={w{%`NB__r#b-kO%GH9rs{kKdmaxLA6L8?)Z>o46!XZbR;oIAIym{P? z0+yyxhiwkn`l%Z)y_STI+IvY!*hv)wPm{`#?NA=>jEeV;;nT2taBoOY-oHGWtit`o zy??U!^>{D*Im?+VOdrVp`>(8KF*28hy#LhfrbedQfXDIk~mBabUS|NN%Iy&EMrJPxPxG|!E zK;;zP^gckn4(o83{x6Z%=5yMUJ>+vLhc>>S&))B<=xUigOr5<8<}%TrG*wEs(ZKZy z0;(-vf$ipg;uiaZ;{KBd$i6U6NS~*Ozc|!Wd;l$hi zyyt&GUnt@42WsrJ4KxhOU_t&=kvDj7OW*0_8>c&@3j6Tp<@1D}MnRG)=i-7J zA0R7dGA=yZf$#VY7bX{ng5TmV5NaAm>nx;uzQKqm?^=ob*NhgktD?oeYdXu$6_>+l zh4<2|vYd`X7Wb+DE7uO_i~jm&;M!>|bj~T@cOL!dZ@_hQSCXEwjtjwdTD_ocDnQz! z9{lpT3w5<*paC9uJfa15?#-9AjF&@Gv?+RjIx2>$t4SH_{=BAm6RlU4vGc$Pna5{s zEECR=YU^|%yjy{k@1HA7k9|S?m%HGOPEK&Lr#gMhI|S=)pW*nDYHpd?OalfQ_0atN3e%w@^d)3G4cDH+ zlRFl&&Z0t5W3L+Sn{@{=$9xn%rdZ&e;jO&8`+qp5awtcRET(`it{imth`90KYQEX4 zJ8bOto|3PcDsv($*(SxUwwg?cD940-!BxhjfjpGn82|ohv2Z+CtYRP4p;>dIl4%QpDDK8HuI=p`Q6TOp3sosGHH zWzgd5h|{bJs)Z*q$>C6LVcKgwF{|30tAZ*RjxdVLV2e*22rTBZT*QTi|)p zd+O8c`stas9>JW=7lmtowm@FoLE-rqCyde*Nn>_2G_NcZKI$ZJ)2>%=|BVW3rljDf z+o$1TV>r%;%MIjNBAv#plhu$^qU{Z!LU1O zJsHK`pA-0ou@-Ls+#NfPG{E{|Z!E2|keSZW=h!GmYPe{I;&eIZEZm4Gk27S2Z3Jm2 zTd52u!xy8Tk{{KRlSk}AZ*@tBa#2QZ?2NTzk3e){9IiSUfpqXH{F&f^+Y(;DO>bM+ z{+~7cI)YHA8;tIc*RYkm7alSk0G`8#3GZga3hyUxqJxvB@j#WS)S{e)vH2AwQ=N;3 z_nyP=1;c3kr+!dTTubw}T!Q;noyn}-6Z`Wd@%o3i!g%`varBl~VsOq97-DG)sHnly z$${66a_70DdjSo83~Exh@`jBv>>F1OD-|{H;>MeluwXmgxk9LVdn^1X(Uk}N z=Y*OUkS^Ql@vY|*(dOY(@D8`aSHo&BzxO|AnCLD>DfJdSY`QVeHQ=2O*O1AYSah5H z8joq0^YJbvLh%nBXt)WrjBtle#;N${1gM$nzLoZMBKdV4*c8m9+E;IOP)+2 z1-5U)+sAy-W5z|bv!_3W<3Dqj>)nA4 z!RspADd@c^e%acQXE$_UEtwt~?e0lEs_d}YJrJszFHqZ!e{jb09Rvp&;ELHx@YK*> zU>@~^-dGl3&5fx-4y1~+dRTe0H_YphBd%}QfQO4MrT#?*_*PZmn85LPbKqQ9 z*kCN*{M|*;Dx|!u-?z_`5A0)&N1OXlakV>-&|fPKz1JPS zKh>vOtMs|<^fId6umc|DrV9g)`w2I;NZqeALxzWeShk`Mprt--SIMP}jqzfBFC{L< z0to2xlVb0OihB>a;<|vLtb8?3?r*3@Ppa#L@0DFKHMkp2x3}bn8>HPu*iE<9&Dpvv zjGCSaa_42gz%4Hmtlv+=$#V{{s?_=WTIh+58NWd1Q4MH~Or`k~ov3m`C>Nf;1x<1L zVgG=4aOA&blxSN;@o^iW*)vtPEn^If|0fr4X(=yTlSdb&JoD_Lo_ycn9lbEIgYfl} zz-!%f%xLS38(wb5#?HR19hXAKO`TcEF-MwV4nlU@A`H^2r=BN{2t(J6=kLl>D00FO zDr+?34ZjrdWavqutExNh_+=wJIe(5i73>zbQ9WrseIz>Gyacb-X$x=FBwf)m9S?kc z24%X}$fvg{XWiS)E9OUwB?UfwP;V00Exsx2KPTeHOD0@py#WSWPUjn6*NgH*S27=^ zi7l6&pu+@dHjf{|N_~HUGAhCUV&)C!|Cp-aFVR1xpZ_=6Q%gbV|0YlNALgN;P-1_# z;@o*9adBdB`Ld2r2Uis_{vA>XbU!)SY)+dream+Y-;Y z?u;5+k$S6AW*wd*cd^cq>$p#HU3y<%)G;WKPn(!4`}=dY>#iCURV}<^CweT9?~L6i zcgbv)YgI?fx3sE>Z92TheFRGhi4Uy1G@`Df1!M+ne3)I+5L+KhPul5O+P| zM6Qv}Fr-#P_^M&UgWml|rxj%I&~`rRt$PI@rq4p#m$g{>?i<=SFO>TQ_kbJs_Q01D zsn9{y8b5nG@P?UraJO$!c>tAqrFVzPJK zBWS!ogt~V!A+TQn9_p^dYQfHEyuJ&KY3R?*w%3JA%9FV%%!x}=TV&CPHqsnZSHVx5 zL`x&`IHIpAx6jBEdha+xX~X=mYjB>B>6Ihi(qDrfoj;QWd4lDhsr>ipBaRMn#@pi^ z*h{^?yl`fXkm#KTcXLY^~Zzq0$iGE$E-rbXPYl7ilr%X6HsTVKsxWu-Hg@ z$xa>E(^;KLgWj{=(rsdZS0HLUdmwacEWn7&skDCAXdc=9BK6-P`K!}DKw0M?j4fSD zZBwrCD)&vYy&f`rGOL)B)byxdFB@u)9FD#V*06TkX1?|Jf#_q9D=b-ipXR!zkjLI9 zusGQfTMo29(!N{pE?tG)I+gK}TQ|w1d=vfLk}EOn_H*TxOxUL6$vee`dVG}Hf zt)))0dx6VtBUra`0LoO4;2YB@GCLl@XYzj1tleIu^XCdQk7BU>aD#gZrQF|CN!ICn zGH0!BfyzNvc;l8bF8}I)%>_kbty(*zMJCWi?-`==e0S`kpHC}~xS+eK-RT_vLrx-#>1HS220Kexo}EHYV`5_BF!r2wx6=G6H`$R8Wp{cQ!3Ph7pwQrViLCcw=26y26S-W}b{@1eJN)kKpQy>kSA4`q9){CSR3WneP zdGWvFSh)K?JQ93{PG{=EpfPC}sT(1@N)j<&sN%{7U2)HvsW9P1l<*-$q(!p^v21|} zDO%NwFx!X2E~P`y2rKU0SC2hAF61Tqrjpa+M0(+p%1e9u)A8i#n6P6LoWJai&D#g# zOtUTE*^98p%)zue^eCP#PL~b%FpTX7=i-{)XF zdio^uI{!NUv0KVUXjQsCw9nxcao42|(s){JxB#YlT!cOwMx$N7SETX0QJlF`8>?2G z7KNV*;=ZT$WcRxr{w6MzHDBB)yll|tvc=hOT4|`z(!rMgb~p?-%mOhp{Qy0>;=>T2 z$%RTcNy%yf-B|9z+;<)h+_go}GCs>O!%Se8)p@$9`$fLQEd^2|8@SK4Oo_oIZY+i(jC3=iK{(~f3<)+A2=%Uc3tr9s2xx|*Oz}^G6AF6>G;f2Q}Q_% z2_5^y!|k7ss7KZ*aoY)B4%nvyZ!}uSCD%wSU+Bi;Jd*g~1XbK_L7iQ!zgPB3fw2>JWyH?o2mTQFaJC0^P$Nbp&a&EY<` z#mq#1@EUpumU$dx@;J-p7M<{|w2z-jcf@f&E77tlgpWP$fw2P;II~t4J2$K0+XV~x zhE|MFm|u^60}^5HpJr%#tIZ34hM{Vwzu@kzMJEcaq}<}Giv2Zf@v(s?tHwT;R}776gYcGhBaM)F84W>xIIiOm zxbRQ~l`$Hkx8+g~8$(EssOOVU4VYH`qc+c9(DjTf-)+*P_R($_Xx#-@87E-+qk-I7 z_7ehIKL~FA<$PeP75WDE5e}40fXH({p|8&v{`hYvgq?m#VHw9!|GI<3G!DhiE49GN zU^-7<*Ge|J31Zq485vpIpz||hyw!RELY_S!^Vj~u(vz1c=Z_s-oU6%hUdB*7{w>%I zoevR4QeJu37Vh`O3&&aSV8t;H1##X#FAP0Xx(kE;8Q4ZzTW~~>Kr7#R7wNSqq}kGxpOdm!B6`X`NlFB#rn9RPW zz-fmrkyM1m>;0o(MN_@iJZ-WkrJZ(}>3RXY6u!pbwC-=r))V}6e!!yI`1sBj_Q-&Q=c z*PqLdYy}TLEqK{)2tC|3Lp=J%kleR+<>tw;pl`n$zbwlYKd*>zy>ZG4dhFPXqweg2 z!cToT)bt8e2p?Y@7nkmjg(HLekdLn+z7E}kD;(yb zp2!t8sSS^>tP%8V<+S_LYnV61Uz8b?qRnR)KH{g#2ZTD( zbPR(&@#E=tU;-YuAA{z17vVI6Z*Xfw7VmW3%e`YKfI?{m|5pDY-hVt4^R^W8;k)Gm z{@x}==P9Da@bR!bA|0!O>IA>H@l;Dmm@_3u-n2Z8dV9s;fL(@^cKW8MF--EMzx$!7 zY_n^;Y6t#mS_s|)`ts7xf1y6dhWg}1p?yL%sxGw`G@5!)wshX*=$g~fFDC`%6@TD) zlRA2LJxztKt6=6PQy%$9;_m-$pf-tx=WE>&hOANG?67!LT%(49vH_Y-xkY=P?kB@9 ziQKP~0eCF@3*ouVLba66r`K~3II#V^P+qb{nV0rU#7o)J z*|Yo&^!?kF3S*AJq9@(CW8WgKu-L`-9WG#p``+BLViR|LP(ZFry}4Cl)RnF~BLp0Z z;cI%QQ2X&nYJYeIes0MIn_YX+^3@bfd|p7#Vg2}tj{=P>z5sKK;?Y!dHFuFefO$6g zWZGZqo{ahk7OHB%b|v(&`5w+Z_*dMyekkJXN+y!XyWs`zr*y<-v`AdudGA9w8;e54=<*-uH+m zAyZM0EVNG2&gffMwEPs^$lL>;)k5W+W*5VfibY)ZT+-@BE@TQY;8E9OY3+t&9=k3A zQr)hh`O#R>XIvVqXof(q(Gl>tqc#kAT1GHU2fEt1W6z4tJjcbMLUCgcy!509?6=5p zVQ+yAUS`0Nwd;kz3U&PQObLxIXQ9UKy__{=0BCh-l21Pt#IQ%16BfES zTxKNk9>;w6aokC|{uoZK8OrWQH7LAXlN-K&2Ftop)c-*|o+~`f(p3zG%CfHBR zEgi$U$wur{bW&KcXBiZBnM@B%dsaZ_>*DkShI|J1P~EW4l)pL@yiX3ou}9)NHASRbxxx!~tE}KE|7dZd;G-J{Fj? z!~qZHz9LWcWxV}Qfw*kUB5qmQ08{*q%cgbg3E3AH;-I<#sQz{`>a3`R4R>Q`pSBq+ z`LLKz9#24pYg%l8DZ;rK!Thq}3?z@7h+&=GIJ`Pfto`kcVeNU~>h26<8;!YPvV-kMOA1MnQwE=8K8sbZz zGVIWAALmW7;{fe8dex>T>BxU!t&V_Bg}t%)zwhLbIS8W`TI1!St~_|iEn(SHUw+Z_ zgIdpZmG=A5Xf@V_w_F`Z>r_t3ubUmfyqUi#b%!Q~Ovr!=>3=(EL?s&V9MqWPi^VEB zykti<{QG3gr&cA=m{UpMwb6-hTXq7?bY1qZ8iCfw9ckz7gTlgf(oAAJh9#sOPu&qo z$Nhs@40#Iu0#2fDeh)7ET8gp(S>lGpXR*r%L#W9%M&qqtAUjy%6f_;g43h>J>@*4H z>(1qEzFt`OVFL8LHj?@tjOWdsA3@>P4z>Y;Fu&bYsJfGJ-)WxH zU!RkuobruMVfc3RIMg0_2F^U)1<#Ymqs9K;6rWxp*Zn#UmCQ3?xJM)WeDzV@TfLE7 z)^x*}Cj`DVqc7i1?<4K%MsWUVK1JRdOLEEgXuoUEykZO%;XWznmSL2p9N#N6AylD z&5eVe$=9oOm94f8#kI#IrebtFxuz_ku+1Q zSa<4LPMaq&Q5GtpL)m`#ednoc!NX0$j}Q6$IiJ9^|7n7X3UHrR ziDeoiX~o=yF#BQ_o;;aNIm3qYl$s!Zp>Dx$`A!)7H-(xvdkb-133O)FI$9Mc(r*<{ zd>3?{U*@i5x7Gc)N74@tPk04(1yj-4_Y^FU9TqxX4yXQiP7C8_2BQ0-6YSf)O6>OE zNm`(4M(XKu9QD`@vxc9QV>yBSGGFY~_?0qs{tmg66GCBWrz8$s0Cc>SNgsDhTy~2I z;Bepyd0mU+zr&OG$;=cSqGro`r$+Ge#f^OR-Z8-;RRQ}M92IZGtMjc~O-MK%$0{Aw zx!iUFYbHq@gqRRKGI9|dTxE#|)9ujyPaf}IBy|cN770J8icWrxq0SF4%Sv9X=Bc`? zX!f!X@M?yPyL8B<`NyR`(~BaEzGY0k7I^WtDrtVyKf=~It9Wt1cX(Hv#JVSMi0g7Y zbDHT&n5EQH;#4_`g^Yd_lueVXSLp#mB7lul4O|S_fpeO4kab!QOjx>A)Z3oH$>aLaXwTIg zF+miKPQ-Cvy8*c5)*^EV!JGVk!bs`NvD~^tJX3ZNcI%a3 zf1l$N7N!C>-F2jt@F!u<$|lP7_yD>uO@z-Q=HW6?;(s~sr$(zGXjb)1eDHSwy2+|x z$u~&{nYWKVUz^D_pN`YI&;XxKI0 zrm4kWulAPSxAL4mrZ<33#5l}u+QT>gMxy*}XZ$eEh|6mwHsXpi+)ykrgIoP&W4axq zBWcz0?~1{EbCND5A8x?KpIzyp<^@RkkVvx^R>CBU2XwYW3bjs2=aYdo;=U3iG`Meu z2k&d6-OftV9Ba=vI`+V~R(41OH$tDftzexz7w4o~u*tm^iTz(hgW&W z5hHl;EN5Ka{!esFH|1Rab7DtHujs?$XpwCn29?9mFvE%~{Wrq#^|8Xj-)R^#VHUKx zNQ{J$wp=f zFTwY!En@$(opAIH60(bi^J|IKuWF%Bci%~$)6W0V`l1u~W<@d&+~-a%QeSYM)Dy~_ z?nr}Mhhm6YXV`q9mS?T9!XQgU;mFKvUJ#jv0SlDiTV`+m(pUq7JX0Z9gTeY{A$-$T zVP&U1WH03nyrQS_-3Q^2@a-sC9o{8W4W7cXSq|)XE{+OfhT)?4b)fgaN_di>$$u6d zq>bU1dF%K)L=%Q%utpLFUN+%F+hb{+Y6|HG>hbb*+3?%Y0l^apH*(s0=QZ zwV4m(!g-JIXL2cQGVO;~AMb(4$U*3C>W9Nz!g#|MZ%7(r&b_5B_0byXojtofaa-(I zY(3~BUTG<&@V^N-$iE1~GxF`(tcR3wFG(bT;XM1)A9ZgU?wynCt3_F?r7?_En2ci=U{8mjRah{Z4V@|#$R>2DZLPky=MUhh~T zVy-#37i>VsnnP5g5(`^SwutX9*us_WszL_^O)TBFg$|YU!ff4vc-Lt+s%M|XV#i__ ze?XNl)rUgpou{z;(?B}WT@|Lk?u-YAj^xR$ZtO%leL5X%&)JgWB@NMdLneIdPzUKbO+t^I+bfP|^f`NRat%~Y*AkR<{Bg~~ zR=H;UFZ>O9SgkaPTK;%Rj2a{Ov)&$x?R(*m{h{ZAllhFD%15X4!mX+$3&|>CYqYtrR-i z?u0Lv860|j4aQ51>URB}cr`0uwxwDhE;|iorF*}q^*{{Z*~<{=X}?h z!_lW)V8Q1=_6g3FFE$!2nvL2BH&>n~FP&KII?0ub>Ylrv&FaWQ6l3ANSpuFI)k)|S z|AzJyC*$*~dpL4RDd_FpARJbZ3#cPNiA+=C;ezVi28M4mBS zaoe^o;4&(KuKX&Yiem+!bG)8p4vY#TcjMun()lWJ!XH1*;|^~T9g3%*O>qiMyEPCo zRs{|F9E1s82k1vm4J*ZlK+&_qkQ{a#JTDZ=M@Sv}A7@XKJg_64zh}UP-{)hWi4l;K z9>Uch-@%U1bPied6xzqwkebII>i2ss&h09_EMnnoQrT`x9$D&qviT$3R$KR^dX2Uc#i!XHu>*J02jsB~gZ%_xxaA6mRZ-U}M`*3!2pj+iL%NNvNUPRC~> zew;cJ!h)W{`ThgocS09oLGwWD^x=pw@|F=RCQOlyFWJjji+oS}7VS(85rYO<;D{?3 z{7tq2mR8JSqua6Eq`8%|-ULEUoe4LN&KK4i^~TcT6*T|a5h3M@9k&^4^2wrSR8bef zYv$Y$>leS}o%-#ty?X#w(_Xge<%+wuWa6BUZ^Y;bTdE#(?aadHSyGod1->mPk6++pjE$Q`QO{sEO~fv z(tRZcMQgH=l7J698qsU94o`ZzLDsarD}Hdd=lyvJkXv*Ny4k4GlA;9k(%U0^UFD0j zGu_Z&T_}}qnN4Rp%;i7T89Zg~NM85(EM#`>X=&4Jtshj+j~znb8>?lE*LOqs*2#z0=18NP2G3=Nh;@T&Yd{WRRnBaiEg0mYqp zY&R2D>NFA+I#vpo|Eglx1yxQR;DVlRx5d2o{(N?=9Ullw65?g~bZ+BafHk-1!<&Vi z8gvv1_+xOvD$7;j|Bcjk;0w|3hu<(~}rthzsay`ayg|AMI9E1nnm$*678 zXIdF&%Eu%wXT8cE^j4}8JYA<@$BPB@xh@56yNtqL`!@>~zxQ*CERyy8KEmrQec+1c zC-Tk+=Q@+ulyP+u>y3Iz9WSZj&5$GbOZ5f?U9y(W+W>mxxEs3<8;-`-l`t~!4)Dh( z^fY`74?25+(u_>;uik}HKeR{*|&7jxC*zKP*vY-s}gWT!ZdbxyH_5YWr=CGQz&-mK2SaE!@DY0qw((km^9i9 zGmadG&CTX~@7M)8;n4~Hy)wr%y{^3uWTjQOsK3hNE?fc-y`z-lkys@@H> z`^y>mh!;}7^N$v!j~qdphTI`w2B@d_Eo$N6|YEH9zKI=lb1X6;}?w zq<-B$sHK247kPr&8(0-P4&6V=x$r?EZF+PNqE;o)?Bb4SD8{f>!A$X!!g^SwbDciw z8j*sPD|CI3%P-63u*2DAd>b*C!`{g0T#XZ7(bd7Z62q13H&XXEIpT5G5HR07h(m1* z#EZJS;Mkx9GEnzKZU4=jKP>?w7kXjws3`h8CQDfRau=)G$SFNz2I$BWab$Tn&~@G; zy!|&12VZNVz2$k_sp*Hz_w;@yzk^@hn?WPp-$CSyi?HWne^%L91$T!XBe&oU2#!{KVs)MAC9?i#y!Mo6Durq#o6e?VZ?Iv}6^Z8?c6W$#a zkC$4K;ho2943pkjJ9J8*Pm^P@hqEZ+ge+L3@)qouTk+XXpQ+0)L?tgPK3Ba3A5C|F zsNDNBP`V$liI#Fh|5~8FT>-y@nTq{B*7{wmSCitdu1#WGOmL0Km#Iyq^iM7H|arjZP&8y&x z#ou99TnbU=U$Fn4Bb^hYu&#p(-VDyi@qe}n8=b$j`^%0+Jb(F`tC)!Zp}jd-r< z53Ni{L}MLC>RtGWp19wE`~yqC_rP9W7n2I#V=TG&^%*EA2Gag?9z5j{ti3%CJ8M=KDU(deF+l;5s;EQTbe&@c6 zy(ZRI`Y7~(_vadDL+?bPWzihGF|?5`H0@%`f|G*ftOmg|?<>XJQo*Acvtd@}VYqat zBWp&*^1R=JAnBGlSk(TOp2s!Vuf`s$H9a|C_X@sO;X^J1(>P)OAHlQD2i<1*@ZPi* zI&FRh`}~?oTY`1C>!G0-Z#JGbk12+U_u}Aru_NF8-HX;V9>oLc6%@B74=l7#(2cc+ z$?~ltJ_^pE2%lJ?=)RA*!tNBc{u_b|I=YMV5*DM(RGK@5EWy{;ym{2lD5>)@iBt=g zaF3T2^wx0!rHHTS-54cKksNC8oqgC{YnIg6XaaBR&wR&Yz1Z?Zh5c{@~&dnG@yI#~&k7Yi1=hh|29l8Ns($?^>>Sv%6TuQr&iZL<8ghyS`ALZNWCYoDIagx|(e~cDd zXy6L749e&t-z8_6uzn`){MC`~O?T#js$21e z+eUn|q?8A{l{g;q+k?-?N8`+&_87nGIV9KSLErNyh2DSrQt`WHusUlazCF8>6;3R| z$h6)x?aOj{a&?d}FJe0B=8a;H5mC5y#Za!;|Bn864?vfsDl7|_Avv+O<08cx3=h}^ z53fw-RhPzMzf~PEI=%&#pH+vdGKqCiA0b%Zd=0AW-T3=jL-;ndH_khKMqK=~oknUL z!<+xc@`UgTZd9(N#wlBcURGsT+rb)3?ppBVxkq81_b@o8JDAU(OvOXRDX8(;gNV# zNbi}<>Sl|v!@zwIq8SRMV@Gg)RuUz)Zi1KjKf!6rUh&pk573jiRGHHGbET>S(5eby zyn73o^sk0t3qI0Y#qR8=a+-{?dr0ThNlKOW4c-N_#NQL$!S%Z%%rY*-Q5qgXR)0AT zUwjT?jE_;2#Cn&x6$fq=6_DhXANp|D71@QwTPLt*o|AAxrNP3)Bh2E)id6Z)! z8ZPh`E?X#2rJD>ZudPMpo_1(7zy)z~Dg79p18wQ6(A{h)pF4lB^5Vr>avbK4=f~{8 ztdb=t4dppade)b=hD%<|Knyuu4xxXS@XgJIQ0^8(v%0my+*^*^aBGCbM?3`UazjyR zIN(KZ71C){X0tJpLn+=3z1!m6og02+D02Lx?a8m%Ns< zQACWCXP(F}pQS-d^&|-1%iL}FF8nx7n$3<(Lo>|~PQDU>o$ZUL;p}Ue_D6~8dRnl< zog^xC9|_AkL}Beae}3Ot>O18pfZdy1mc`w!T=-lcE(p@IT+@ix*GJQ28w)-q?euE; zrHeL8o$22992(+wTWtEe6Q<@@aY@1>vb!12k(17Wm}8B_xoI?VWD7Lw{h_OIlf`x8 zW$bye1DFo80-wO!;9=S(gq)o&tV@=hO8LbSKkpyRe^&*`@kv;umrXy^k8@((U3d~h zeAlQmswK_^CEW|+)RG}+B%YxwuEv}ty0SqN(9DSoU|yK6#G`#qgSE@ZXL2Z7H3*n8 zqMd3dUXpDwUC8xqDfssKY1nk`5PSSC;xo-*=sL?1W2Z!me(mAVu=fuH^qPzp-sQvM zyQkshU4K56?}C%OX7cZ)l?)Zdw5xh1)i)pDcQbUbe@H%kaRN zmZOz$&BX+}O8e?zQvWFXq8etGr_c+#P}nA&VIE_N(xWVeyv)sH>->#$6#qi~>n2Wn z@mSbbkiy>Idt!dw6h8Vg08eWk7rums3ddWM#lIit^8yLgsO%67v69;{;;#bF;tnpZ7cTT2j75?U=kuu%U@+Me4VpIM^_90_cZC*r zIF-WZwk(H1PZPOw=|R!w*i7D5x)d@N`eAv+??@+SUUs-MzSQe~$cUjyisN?+^PPZ6vFjLwqQ#0*;Yrf3Q`{6Ke66&8`|0(#i@qj@TxdT%1KBZj+-J( z96t$tYkET6)F}{(cO=;E(Xc z|F_Vz^&n2DJiyV#59!&h3-r^~g2(RaUTHI8ghX>T^%7ZeGu+_&rp}9c;^18Y6 z4i^&+(Y(Yf$8VR3S|aP)bP{YVcSHZp;V^OJXtdL?qm51>xbr!QAt&Ba>-Nd=VXh{a zaC;tpe7>2c+9>k|i!UTr1>x43B%HQ8mZyxUfRC4~*}Z%Nn5q2-UzeVSLF0$;vcD$S zRym38jr}FGI8MUZf>t$YC5Fw0j zVjuRNttgML>ce}#*6@u|Ij1XW;O6vEU{#_?>o$jSqv>vbQ>TH8es1Hojz{Iew1mgK zisP2U!*F|F$$R>&8!LQCl$G5+0j^n9aOb=Sp1Kgl{mu{Pe2HNgqZi4K+WsRW=S1#x z|0sp4^urZlGq^~MoqY-*i+91bZ;GIHkv*op zS;y5oHL%CaeZtC<<1y&9HKrY(#`!9?taj-<37WR}N&gy^m@9G3(K|GHWi2Fm#A8w3 zShOszf$4SOxG20gXsQHqx@!f`+OGmvoiB=er~2|qm+kmvely+BF5|!lNIeEEfg;I& zlV3N8-CsP0hZ~c{r6U*cWCsme`m+y)S8v08&PXHvIf#xJMHxw5X-JC;TVLNUs+J7{ z-AH48eN{#5-f0Pri#}X=??@h~&b7n3r3>lov-x~emI7`{g9Ue&Xg2($0GT-*(cgYA zhL@Mof1Vkfa^oC$N1hb8?g%?B?2BK!WePVwe8V5VFS5057yP>SAB5V=;f&6EI5Oda z=vX89$sUf8eH{84f`85eH#g&Fne9QXp#?XolXQYgz z51lSJg1;x};r#a{_$FVGGd*m0fV;im^v{bwlTTAl6a&|XXS^G%X^(P;sm6n4#@Sv`x+{eL?k9J>(wRcj* zWzYNLu;CSAmxB#3ZBR58{`I3n(}oF6s}r%4agsRkcVngH%_ZF5=dJir=NTlZDp%En zY!e4r8uG#bUGdhNY%HQN)ao87mPp*-?$H@yzH}B&Eh|KwXR(~{qkw13ZN!x!*`!;S z4$BKSaMBiId@`mhdZ}-rxTn&*(qlNk?)MA+>-`33n59_Y@P+p7Z>P9^Az*iRD?ZtL z90U9=2>*6eQ-ooHbdQLUUDwb;cge%xRUavCygirphs?*JgC*AF<4qKOYPtBDdhq<7 z$?!aKJN~FO=eYT=g|L7SjJO{`7dD-gmm5pY!R!0E;(DBD-6#t758bit`72u7f1liO zdm`;TI)<#mO+jPGJ%N0eVVYH6x}xC1=54r{isaArq6 zeaJM&K}PT4mr^_}cV|46J{0yJEQMutpT*~@U9dSY3M;gbKE#iQn(6`6C-bPFxYZ7p z&0WYE{<)y%c?$F;$Nk>khaGPv3_uOnj=1coCSU8P!6nV`{Lyp(%wMh7S>!H=+x`@J)E}Q2G5*}q9KvmI9193 zn5$0ZSDzPRQrr#NXKjLNmFJ=Rp96TsL7fk*F{NFlZJ@I1Dz+G_pqu+?A)#sn+09qu z)5&RKgqPISn;ee{=L1+ASTCy1jHhm0j)B&ieW2xbS~yc!EW8W21f7CXS=Vkd#*R2C zPd(TZ+yCuj*MAY>)KOQ2Q-2MF#4yQ6lpaaPc2C5y6~<&#I+Isey@yqCjtHdUwBz9_ ztT$TARR(+EU0ohl7HVVlFEjYFx3Y422Tg35w2FrgNf1lMO1~wlhv;y|6|vOH9khR_ zNTXs5Uz<$o^{Jv@~uQO~Ahn_wO zr>~@tmcxGTDBUBsKFX_1TDcV~lr^!B>tWUpPNa2 zpE5tUiK%}Qgkh1}#K#urVN2}-9z8{3!*nlaZ7EN@Math#8Yr=}jz1B*+^B_XMUlK- zBMU=MB|8>u8v^Oy%<#JNIP_0DMq{)J$vy2T|GPE?{PQJ#zkLm_zO)F>U61DZ1h!+{5-az$?b9&v^gHF^bsGK$;A~LU(ky& z2c+GhBE!X7)FWybIyS7w8ST{&@%bYEEmUE(?83Vd;NV|}c;|R`S;QDeUK8U9 zc17QzuTmfO^mgMGF9TF*I4s=_Yk7U84;lDhfW1AtQa6_XHktbp5^p}H&I=y%XZPcr zGkhovG7sQs6Esn^Z8bNpm`EBu-C@Bo2dTr6AopoGC75|F!xA66QY7fwM)=+xb!akwjVneb|BMaJuF!;f%Ugsg~0)}aNNEQ477K^uWnfoRJf0A zYVP2gF7xnayD?VHmAnQ~A1HiEAG8ibab?3aSfvnHS@2O=V(sX0%kBS!PK}9peQgvU zEB`7xW$;l{eer|No}7T0F7L=uHG!O7_GHBe2~c;?9tZXB1Iw?T#a|tsqD9$Tq5sKQ zsPa%3-8x>zwRbEq=g`zINw~8T~l&LRb8^)(JGeDB%pLxAwYZH5{K| z0O@+QV4C*~R_xMr>J*{JT`ueqmHzC7Po03bt{=w5$$C7*FP7WK7&$t0@6PIqE4hQ@ z=4slufV~epvBBsr7#Z*k?!2GL6Nb#DPhaA2_=0}?tg17fT5rh?rZUVOkSvZ!*h)%I zM&d$)AGFrV+|hPzJP(-DTxr}n5*3XvKzA_?yA*cA6ODRklpck?LwBRg;IptNB9IHu zKBw6Oq}`&Y8;_isLLa-CU}9zp*Z)?>g5r*xst^QgF2wK|`Fd_TYbZQcQ^Wg*CC=i* zvv5Agk4ID|um);imP#$3P}JhLS~66R4@a$!VWfUS57$Ht;B{McMYEiK__rX{F&G|rgM7(TTCv%+8mr^py*!GzrPQEb}ZA=tM+oORtn{Nii%Deb7?EqATYO(g+ zm$crwj?U-2qM+c;JW|C8v!5BG_lqRDo*V_X($1!9-7b*LT_u0?oPiq8h=XQ^3;+D~ zh}}-#cZ^uRT-X^T@#8k9!BK5x{M;`Y)zo}o(@qCYiyut6PxRO`BAC{n?FFs*ci~%@ z7w@`0iibNXIoXUb$9v;EvF_zP^3-D7p9=*Ttz^20=?yX z;_%by{IJQIeN#d?Xxw71F$%_0;Uh^gI1%F9%sFDuGFsP9@}q7vcY3sR670yCimSUj zQhJsN&%UpVMz^YA?{_CQZ)p&gkJiPs=$9~Ld7Tib|CW|EPsWgovGD4}0}5W}4oz_@ z9n}|gTzCoGl{W$(o1UY=~;#3!zLN)vH z@pzS#A-Vew<{diBz020qVm=Oi)=cEB-?LCKPX=Yt4o`-?rrqmIQFiPoE5k8 zc{l0ZVpcX8%(4|$wEv()ONr_9#f@DJvSE3r0J>ST3X?zd!TU`^QFc@MzJFcBL36J0 zn)w$YGtYzHxPBIvc^2WsPba~^elztoQ0AOPL*Y+Ft(bK*1%wPu4jz60Q*z6sd~L1x z=y5K-R_!W&%}=ANm1*oSL!EPOSn!teT1=Kkt&Sh7DO7UFEcZ(1iTl6OZ0oZelq8q; z|7FMduKVy}Xf2$*;)yEl{dwL>4K#Sx7k`_a=F^K}X|euYp`baE0%lq9q?I<@<(d}i z=ZTdMcQTcin$U$+PvC@E4!wTRlWSjV!n)XnV5OpmJ`c62Vt*ix*|M3v+_q4ZsV*$~ zVZg%MD^R%Bl=i0Ni?<|}^@cVj)aiHt3|)W|AMeCPXA*^;yG*FH>nxnD8^(VnZlId} zDxOz%pB@~a$fC}8@L#+IGmAUOQqO#W(H39e{hnAnO4}iReH$(AJQ8a^=?TKCLA=@L zgE&?*7tWSm!j=AxJbp(st-aC6J`&?rV^lOv**F0cw(a7oKe2c+e6Kt&Vih^I?#J^P zT6m+Ul=VxjIm5kd9gIG2!ygrH*gpT4eBRCwI+XsIR2CYcZ*dU{C8l)r{s-9e-AK@C za>A(%>-poAXaC1vxZBghPQh8?FGzp?5Bva||K$h7zc?;mw=Th9^sgndzBS3R+2`lU z#vE4=j@f0%%yqKmd+efQ^L=}YL4uC>rZ7{!dV0KU-KR&gr&Gy%7A{Cl5C6S_ zI+5v4^8zwWTS0F$=8^Y~2jXPSTd@C>8ho2}5@wf<;nhmoxM$b^SYUaC&Hoxe)}N0g zdo~pp&Xa?p*k8Dty%G0?Tj6n|D(+c#9W2hT98(p5*Phw=g* zrL4@6r@xco%=?h&GZ_7~>M6*v5iSQ+imvl4C?H*qZ`F6>k&(XKYBz*^p7rMS3%22h zr}NmvSYo*Le+$O)FTw-g%MhDePG40zah+c#2HsTSxDQ*X`^7%^aZouN4vOY$+j>GK zIm7M?2RK*Dr1FZ$=8MHKHiJ1X~&{=aM7N1$d2l8K1&Z1Emn7Kpf(anT5zVqWz zTI0dzY6p5b_o%K$FQFbURt$m|d)_L&ND?L~U zafGi&3k8!!rox+A6>ge13XWcqbLHx9u&>ZS@Y^?#zf0_11?a&$AMV7x^<}cx*v=eQ54|f%g2%!JExS z?7Sd`sbhcG&@UdNJC{Pp&-X(8!Ya^6@u)Y0|IKs$4{N*|e_oS%N@6S1$(0D=q@}eI1Ij0N*eNse=x<%aH--&m|-WQ+N z+OW^2K^RsvjrOa_;aYj3aMa?kc;=WgpA?eN&SE6S%pS%QMo&dQTWuVCxlp!aSCBly zVhihQexv0Vr{m)PiUf_5zMT0-AAZjp!hu(x3x&trDD063S^aoLC#EU!?)`-#IonZ2 zyD4vftjbH9bf~(MC3@L^poj}HC_KN4iv2?%ee()1Q0#+ldov;2xCCUcM0SW%LEY!y z$))}fUzr+%!zzwKTBR!ZD9ypL^X@n=`y{Q}r;STW2IKva1=J}|5x>=R7e_jMAs?sj z;*roqVZgUH^kCvKjQbZ&rPhap4mn)}l`D~?eaVsE#$`h4keR$|x}C60w_Unfx3JdE zi}YN(pi*{LD%y3(!B5rG$k2N*zPT!~1}cV0ecKaQC$ae7wfurtdnU>H^(dh}9m?5Y zp}wGXq=a%zoj81(t01Q7@~v56@b`)?2F(u@?p)SHy?!@1Y+fg}X`Mt1y`|nl#3mm9 zXtU%YH|NO}xA{P6XDka^4r^m`NHgXbom~1s?5U`X{icS9zU3BZd+Y#@oV^dmY}yNX z4^P1#$;IY3U&bm@?%lL94YajMK5(@b-Z}X}nCYO7P+tWfp7vqyIeR(aL$l}f!WF)5rR5@-d+E2gd^~Qqvdm#A0CSJVniY&p|RERx1 z3D0c)0}I|M(@pmh+BQ3q@*C9n@lg_BTa76VjLz^A@Q%*lN( zKt1^^Bz(7Ib-%|Hy!8{hKQ)zpJGHsvn=D>FeLEj|+6ivCYV(iT!K8gvhxh!qNKi2` zV_kDsT<@igry?E;u^}s<#Lb#&FR#T$r;dEA)(=a%EC9bDgQ0(_CF#Vc()g26kiB*? zFK9dfiz2Id(CrEMChU<|sU3?UF?JX|)1RL{*Wq3VwD7#9Ikp);7VY<#!j-A+XkX<_ zqx$@Ul+~ehC~TQ{c)kw3Sv->-B_^?R>_sqIYKP6gpHuGp67luXOuYFlAHMi1^8&r! zG^p?gZEuS~jm5pt!)-cY&Q%QE-Uh)njbIqK8RlB`#2Zs~^4aFY;-3vo)MZ)|(V9NE z_f05x-`t8yn=0wG_i{{AzAnC9@K=5=Rhi#u=+oDqU+Bi7PjG)g8uzDNXniIK3jW$q zPUl$|XM>O|?f;@=E@HP15!5Z4$v;nzw;b<_Ez>4J!oDEx9aJkGyX4KeX0aSsunOf$oV$xY5O)kH+q0gWow=@bR0F zR<)I!EcdhCo?Ixs+Zp%%sH16Dj$*;+X?U>nE70Iq@ay_bxHQm*=Lc-&p^=B-xbPZ= zj(bnjy#K=g-X)(|EXKIccLdjZWggaRzu*$S3~rDwL>@i}>8)ewHCD-H*1v-Kq&`@4 z-BDQ4U4;2H2B`JuIJnC1KQ}_>HtXzExZ+T#WN2wGlqJc7nj3J_`KJW*)Rm@F1TLKcTmYo|;FqNsxaJ+qP^=e?Mz4bHCpU>N;&t$nNi=vBJc143<*=nN ziLG@;;(u2C@ac)c+$!BYKeYJ>`=j2_xPXILV%`hq?b7ECp^>te-6c<(mOg#RuOd~8 zPGV8@anX0fY4Na;GWXKI4GRm;Qq;g)8ua!HO`0b4Jy#1H-)juIjA$X*kprlo|Cpwn zZ3OjepTs=taC#t4}$8~&O;oQuTKbE4%H-Ooc?pgr1ssDjkU z5W)8GKJvHuE1o>6$_E2C<2o%F-|IM)BbT*`kCbYldrcs>PTB|C49cl-hLmaXZI&hN ztYU?58F-oOf%O^7=*Eu(_H@goIgMASaef6q@m8Zv-*<=+OEet4r)NNa4<(-dCLQuV ztfE_fS+H$*G`2j};>L&>Sgkb&?!CuOAm^EDohraOzuYQHFIEVL5Ly{VIsrKfx8^+-a-EjP7XHuYKB*U8qtH3IaK(HM&-gDCX-5{mT|b1o zTe-l|_5WaPu^Dy~b*azV3-EJ#0sS}oKk@SHXmXnIUA+5x2?wuMlH6|5{5W6;&-|^+ z+9qB2RDg=?RP-7yI4#Y+UzxM&+j7_xtccePbH$ZAlZ1iCR#4QzDmZWFi7T+0{3kN5 zs?y}~dLM#=}(#IInX#RhWu4Nh?>FG99MTr)_Y9^|9$cY zT2>pwkAuzP^6M&`p577O99C!LJHasJ%`?gmvBdzdPTc+}3cSomQH6mHCvBJbozn!c ztuUdnhkUuETpzqz6c85g5GiLOnjgJPnfsf0V~-HlEUXg0x#hxBn;<03PcVJjFELSm zP8ier3hsTrCXP(_jGxd+h^mqj!mjqX(|SDKP}M@-xeE?-Ymv1!xnb(VG1%i#B)&JZ zXQM+_oZIwB^g5-88_IoTE$?=Sfpb^Gl>8;^|8+mLtZ{`HHKsYMqA*=&kI;F|PcrgX z!iu%Jl;f?zn=LkD@KQN6KWGvkZ;)8GpJT-0V>wv)ET1~qcg4?NYTuE%q598ujayK(@RKkjr6_jdN1x;FiaS7F@*|7s=y`J?p)OC6m9Ez z2yzXxWTur9uv_{E9v#0EaokFrQoA4PoiD+E1NOq3_lIcDhdX#I`@Z~RP-ouyWfg6> zyj6SE|nlp2!{7{E?q&+f7;%ce_ zEYZS!1Ks$@dj%e(RxPwSZ$mwXkkw2Vus7BuLTphuXrM5Yo9F zW?uU%o2=KH1M`*fldK&I)}DeCDGSsv`#d&miJ{FqddT9ACR0(V1*DoNai4~fJh5T4 z)OTtY{QV?;Q1E2Aoz%&E8SBKq&a2>-k6~!xa}GL7^Ob|jFX_lZcPOtH#R9Dq`j>2k zA3mvYLgZ^$(|tVm6Ap=YjB>@Rc~$i1Uj%Hqv!71BGl!VPmgrE`1*#^^gjwFBS?)YU zVke!VGL?3i+MzpaJh>S22bW8osS7yhKoLKBUBvfu$8fdMScuE;!(onUpwm^0%l_%` zi~ubR-lU9Wou}c~o1Xz^t6;Bfefi@>BR;<@R=#+C8f8xnfyXWVSyMa)XXeeOdvs6K zZI2_wgHwqi}@B7T|@k25-V;B*P{*-pZDU;#iQ7JScyC(>z(MHnkqD5rPwv@k97Z=f`5|tKuqBf z*)5AUS~x-zKLoC(=*3=i^GSaQ*4P2d=SqIhx!?UEzmJEm|MENh0p)`h<5fXu_-YX56&^h zorc3@;h+D}(1Bwe2dbF!cTLIXZT(9y-kd?>J^J9rKb4hF6_yLbW8+!rw-2(7A~x4%-7>S*>akA@}ll%dPq*<$~v1~7HYM>us}k#!e# z<2#e3&#JVQGQb%XZ0m5%3=5$z96}@e)AUc}Bqdhfhm|eXxMN`jWE*;Nw@E)KcK=k# z8`le49YLPPldM5p1?(K$Kt3hiCnCxhHBOev4@{8Sr!$@3PYyLI(;5a zuL9>#hY5O=H9=i?IzkS=uB_m%|2mMB%Nk7IXb;mI-$Tt}gX>_^=Nf?eoX; zi(k^%f%|E)-e0niGPXAh|IpwIfw;lNOGs$bM^V!ehpu&{bkF%XWU2;i+qepAMsEkT zMLB3fRDP=~k=>1t$$Rfx$M5frv zf3je&qZ{DL(=fbbs?Ezk&%?RXu0m1=K$BtKTw3%&=(7K*5PI1VSKXMwa%n#{|K>>O zs+mOZRkqWg@sowm;yUtPXa+IK>ZrYH4?goW;d0Y>sQ%G|yFHvv;gdUYc;hZi*wByX zI1H!q^l))gQX5UHmVD^D|H4k=8d~ylA+IKBPkW<3)jd-X);KK@-JMc|c}Z)r_qnMw zJUxy7{4=KgGrtQvhL7fgw@3NMzL%tGJ_D4VTeJ5wEnIPLGYwPprMHVb@$r2_T-`5^ z*6rU8;;Gg2v9%*puY-91h8nitN#*;EPpIggC3f-45xac2D3}=aBD=^qc0bey-ADa~ z{iPuoJ^CQ{9aQD^SC6@Tc{h69Dz!+*rqIg~&TPMa2)c|;qBq-L!n0dLkaMoTb}20Gug6Ry?^WYIT?QZ#L0ZcG9Xp3{vkyhs=0%|{Eby_WFe#H+M5y(bnJ znMrq$&9LxRGWaalP z5v?3{nhdF$?jMR2U$t()AP+x?wk;QCl^zv-o;2m|`RAx^tG7JfVH7V~h2mq6?sOny zK00~~73NiElG{gr(po0Xa1QpP)5G_Juh~W%J24KET~n!INd)AZj05f0!4PQt9JV)E zamU{K(77gB=rDIXXdRx*VJW?F!r@tbypOE9A#!_o7vi z8-?&p0jG^WNG%pos6L^Udd|NLsXH_ItGX73>31RT+f{tRyBB+n{6rh=uT$qJ1>7F- z0m1_o(cCl9cw=-FBvl2_oZ-20u}zDoJMEWCz&*M>RdS54$P&vhNDj1yy_j1z05(NR zy)1-h{Le$4FvE(|v&(7gfJ>C&y9llhoh58|5zT#q2MRZPEWuNiW6*h3CS3g9 zA{2MDp(--o;CDzWBM4^&KUV@0#S zbp8AyA@psdJa9czWNr<;IJ-#l1??9Wx+uWJ$=5+Yrh_1^wB~^MUhE?EA#Sa8pz&QU zhy}}HuvI$a6|bsD^Nt~Sp!sK|N$1XTgO`usVBh`d9(;ht{&AMg^?4xp8uSu=El2>f z;z*8YWSN^zf8OIhm~>6I(!<`<=xnO1Xx3CjT?{(#x8A#HoA+#?p;y$I`VQIXc~Jvu z_I;JVJWzxtQvbSg-64+J(T5c(Rq^L68C_a1S?(}w4lb6wO*dPe`S-X#(5%p%>n5ba zv;&euVRvu&)b*1g=j8wtVj8LZ;5$J>p&Q5f{}fSqGX}m|&kw%;6rI|mv6prZmWO?Y z_&h1oFmNeo&G5p^yFIwZ!jS@6RWZi;92MO$z{{n_z-9hj);?;8Kc0UTiZUv}dqg}g z-l@m^?MB1G;T~M-(;F9E-hq$&)(MAtw^PCfEw~z&fxUk_342pd(sF}WP_+NLyxjej z#8cA1nptJ+m+#L(B~@@nmMu(;tc3P13k3DHR8(Kx3*++4!Sh-h1z!6>=U30?;DRso zTgo&{&=^2-k|bvH?_j>Zsxx+fJ{?@w6w>n_D^d6{3r7^s=hVAl=&P2_Dwi_oP?veU z?|L_yA^7vX**07&Wyb#7eS&^Xd@r=vzY*^Jmjjpb7fUP@ZHzGPOONGx)TVroO7xsL zEOxYb-%5oi4XA*a+0MAgb|ThYXoh>=Z;5Z~9QmXC0KItI6Z(~Uu*RAox|3kXIgRre zow{OMWD(4<_2i_dOKEgs6nB#NJ^?zT!Q;Fszj*On-hEw^_~@VHuluWvgHHFsEX_=) zyt-7@?Rgk39b}5(kDkb2R5hK{FXOXrFCg}10;z5PjMc;MLByjautYCXjNf>IR(G}& zE_yE)H_jP>6Rc)qQ=e*RD9}Tj3^V-qZ6t2!b_r|8H3+>QP2~i+pI8~$M7Dnvd3|SX zhE)#u%r%1)GDpe>HVj7xS4Tll%4kgLXRv22H5Du2lE`Cp zByJxaiTnnt$GhW`VTJtM@(mrz*GDziJnrGrlODVah3IwFVxa#<63SyS=88F3MW#}i z!d9y5kSPnTKTlVKj4@Qr9xdNVJ-V~&@YH{Lyu0`VrDeGAl$$%D`b-XtEUu!R)^@b` zh4h(U919Z!EqTj;!?NAoPeQM>1k(ST0Z(&xU^g>gu|TzwUxcQ@fdlVg-QXSKmZ1_m z{mW~b(d8aL>*FpAO4Vki3Bz%l_62#@HU)_jq={M2J$X|Xd(pq(3S3gy28P>{x!+w& z)KmT_+hHutSOV42=#ncv2)Aahv=LIr^;Ts-#5B%s>50Rv^=R6`Bo2_Y^1j0li)&7V zAsz07Z;u@jhtoa|t69lw7kUdrv4Gl)E%}FCmhdc92~XJPka+c<^j=~J2DcDg#ukY% z;-z@Gvo21`)ZxMP?o^oD4|Oww@K;U@>_46eKW%oQsd`T+Hm;)OJ&DW9`-+!Uw27o% z^t_Hkc)WU7T=nMypO^+Ts34gvw<@zNL+X0gbwzjIVtQ{4>~HH&eFxh)_HGD;2g|oX z`Q8v}Rs#d_PSeVm`Y!>{7CX!9_Ls_0yB9%}Un0Bq9@g~dIDOU+aJP5Okuk#Tr87uwK z#IFA~(9-H%@GP_#-s4DU#+4{HFkt1?J;?H%VP(x3V_t1AS8O#`$E>nZqQ;GzWGKC> zJsx~h+!Z;WOh&15f!`@AU;Gm~WR1pz!A9bv4yD3@rW@kB!gGS7Vg{~MRpbF5LP@Va z2e{ViD)Tq^1 zw)_^A704hpIRrb!s*;lZZ}H5s>$v_MbGpM9a$4IFPY1=bAWtBr+*V4lP{uAE4m2&)VmmwT4NP&2( zJ!tT6B$DrJ`F|^y!$ieDP&U5^##zVWF0Tv>(myYsv&RePT=(Z?(p|>F<+DsVSq-J0 zBJSL;!oB<1qI=dbhFg8O_3&_ZKcfcW`_D`JTMIn?au@wIb;oNHrCh##w%kT?yjY&`;%vOZjCv1iB?hCQ zGfLW>7_jr3`|vk-BG0Z}hTSh@@S~s^{NpTBt+)+$^)IARS4V-vvLE97GrqKq|KaRRAF2Akw~sU+g$6__L`9_} zarRm=mF7exO3@@lO7nz_MW#%JXf7oUO3q$OQZx@#QYuZFK50@Z%5Q)Fg!_Krfv5YN zv-f+ibzQI59&td5IVP{sh4Lj&L}!g-w5%ad>N0Ea3MrT2apMWZKDTF;5ksUI^j}Iy z_2ZPEw`G$qcEa^t7b80Fq#oCZMteGmdndM#`;|zr^D-4yAGO6D8T-NhjEEk`zf#Wb zV(c0^7bYL*Ecxadg`ytb7}xO-&GWJ1h1oyh!{MEvwIf8dw3{HNX3T=>rPDBE?Q*Dn zo=b7{({R8R6P&M+#5dpMqQjLdl5j>v4Rw3_T8w zfI+?U$kXJ#s7|50D1A1b>!?F~awYp;lo&X162B^EEw<>^3pZBH!|2X4g(iDHwp5r3 z{kD11qmx0y=#^2;Mvls3<=1E%)52Ah7#-PrN7sP@$>_5K;d1e_5 z9uUO8YJw`15)wR9u+C<4yBnll5{Q6tov3@h11! z7mjOlD+)^FTA8)hl_)F%d0OyTQkG-k97LQVD@Or zVo*U|jx1*lLuNtpV%CkoCL_vb0?S{ z#jb@$uR9dgVHGS7u;(0?j}&dp^4g5cbo!G&6<^$nuVxjKs(lP!`R_D&M|pA3(l9>x zCsn+!dlo;BcqJcoe*riZ-2;;o#T0$wJx$#aMe=*+#q7C7aBb}la#;NVT62$M?E`E0 zzD0&RPg`L7$}U`(5kU)9cZF*w$D*14B($4(nZ~(RL1=#~x;~;m54TPre`8~?jk$`h z%T`PKYG=^$zd-kAD{!U4YK%r^yR09y`N{;Y{BFW}DN%IT)sgajJMyUVlX9m)jud0- z4c4{Wx!wJ$X#3+fv_F0h^_LQ;J#7hIZ&#rnyHbR!vob;U-W>*?+6iCQPG{T6i>XKb z7%1sE3$HBMLWZxx5Wh|0Me^SQNptLgym|bwGzRKYb+MuR3B-iw;9`?AoS9ijp|zsEjp939Tip$<22hNu+s6L$ks9nh;9~s zCfyP;+x|kkl!eO(&BdZ5ZPwKp!uc=bg-U(NFSgv5{+M;eP2QiNK;pAGp4$rdq}=bc zAXk_?UWV;ezHHjNN@9pDhGn)1IE4%0T&)K!KA%s!K1M+Pw_O~f9!!@zD4}wb2HIKw zh7Qk0g2Refe73bSPMu@UYTnBv?^*y4oj(vWuFhi8iWkfu*U^?UarC-8hiXD*@;vzj zYSH#YkE|;&QsV7&FNhQNoUy`p#WUm=275ppg<;r$c-)wi3ohp)fIU3gwrh!LAUxkanJ9ccN~NId!7gSSZMH;osTILf6`3|Y#s z;@=p&GjJpd2C*<|+3sZos1B0=j-w!@2J^3ipcrIOOj{>^`PlaP0qu z^CLfrXH>7EV84qz*2Tc*roo`_cmg(>U86ZEy?BlHSW1340oNo=<6((Wf=b^Q>R6T_ z`Gym4)a&=OIO!MkJaCSVfbN#afp8RhI9IuZhlSn3yPSbFjTD|O-`DnVL zb_A1}rOe5GKZv)Katz@caC^aL%IGnYJo`wDw)2+k{3w!Q;~J=9Xm>t&U>E47SYYe) zBXnxoaCWcW2%pad@zwWJz?YZN#ZJ=sSLwQZa%&>2oz$CE{Q6Ph)k%E5>ZdTy#Eh4F zOyLjq{-R;VD>`|iA3ZnJ=8Auffa@o*`vX(9j9x`eou|-1-#g&+<0SoAXim3lv!GyW zN31hRr^(iR;O#t9^qZKE`p!p4zVZuuy6xi0;dvDHI7hf$sDy0}`m{or0T-2|J#D|I zw5P*KHr;oRwI!B-QhIloFg^@E9Uh0_-ix5ZB7#Rf*5qCju_$eloV$rKrnV&CUetb7p z`MVN|jl;O<{22Nha2eiq?@YJz(s<*GRD2uL8<+Pk5P#*#XxrT)EE=aN4&0*G$d;t8u^bWThC>XnRJj! zCobnk(>G%N7-b5dFq5^P*NI|b7c}4XN=)9j72hxD0RIvIzuB#k-1HqFYg`lP6GRu!Tqp!3pQ}kR+1$S1_Ktm_|G|wMW zzi4v9@FeUJVh{dPJE3}8JN=RJMcVJeL9Tv@-Vg21iW*%w@YoYNa)F`Mb~$UePrzVz zq6^*AxboIQ$hj)*gu{w?*ZkKsr0pPgeDsvwMqLnTnIbMeu%2sXjN-bw&oHZW4La{OzkLT%6Joe|^{EJ^IF??%54+yJkK;vc5|7&nx)Oj}ENX+ZvZS##A6)uL2Q=rr{goR5%Dy+1mSs6^5?BI8$9vh}d z%0A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

c${fBGS_8jj$-%^N10q_5u+6fcINbdt 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øxs0hGpw+G5{QwygwTjgh1ll5>c^WE~lO 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 Hjb{2^dWsUZ literal 0 HcmV?d00001 diff --git a/playback/playback/obj/Debug/net8.0/playback.AssemblyInfo.cs b/playback/playback/obj/Debug/net8.0/playback.AssemblyInfo.cs index 5894c407..94836395 100644 --- a/playback/playback/obj/Debug/net8.0/playback.AssemblyInfo.cs +++ b/playback/playback/obj/Debug/net8.0/playback.AssemblyInfo.cs @@ -13,7 +13,7 @@ [assembly: System.Reflection.AssemblyCompanyAttribute("playback")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+9f7db73aae63536d35e02c009a73a2d19a4a6e8d")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+6c55dad574f4c42903af5b9996d72a8b23b25485")] [assembly: System.Reflection.AssemblyProductAttribute("playback")] [assembly: System.Reflection.AssemblyTitleAttribute("playback")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/playback/playback/obj/Debug/net8.0/playback.AssemblyInfoInputs.cache b/playback/playback/obj/Debug/net8.0/playback.AssemblyInfoInputs.cache index 6a8bee78..0b43f246 100644 --- a/playback/playback/obj/Debug/net8.0/playback.AssemblyInfoInputs.cache +++ b/playback/playback/obj/Debug/net8.0/playback.AssemblyInfoInputs.cache @@ -1 +1 @@ -31b111defe087f5513a86ad2324ba79a87d15b774f0b496a1f274a44a14013cf +90ce4265b1b829b754cf1927d47385c4c959368f721e3693edb0e14039a808ba From 29e8b76c0b2c67542fa06f64b9398add8d4a1827 Mon Sep 17 00:00:00 2001 From: jxd136 Date: Tue, 2 Jun 2026 09:55:03 +0800 Subject: [PATCH 2/2] chore: del --- logic/pve/submission/agent.py | 931 ---------------------------------- logic/pve/submission/model.pt | Bin 1249 -> 0 bytes 2 files changed, 931 deletions(-) delete mode 100644 logic/pve/submission/agent.py delete mode 100644 logic/pve/submission/model.pt diff --git a/logic/pve/submission/agent.py b/logic/pve/submission/agent.py deleted file mode 100644 index 83cacbd7..00000000 --- a/logic/pve/submission/agent.py +++ /dev/null @@ -1,931 +0,0 @@ -""" -THUAI9 PvE-RL Agent — 纯套利策略(v7)。 - -核心策略: -1. 开局抢占算力中心 → 累积 compute -2. 获取 TECH_1 + TECH_5(消除移动冷却)+ TECH_3(容量+50%) -3. 跨市场套利为主要(唯一)利润来源 -4. 不采集不生产——在 volatility=2.0 下套利效率远超生产 -5. A* 路径缓存 + 买入来源追踪 -""" -from __future__ import annotations - -import os -import math -import random -import heapq -from collections import deque -from typing import Any, Dict, List, Optional, Tuple - -import numpy as np -import torch -import torch.nn as nn - -from GameLogic import N_ACTIONS -from RLInterfaces import BaseAgent - - -class PolicyNet(nn.Module): - def __init__(self, obs_dim=82, act_dim=28, hidden=512): - super().__init__() - self.net = nn.Sequential( - nn.Linear(obs_dim, hidden), nn.BatchNorm1d(hidden), nn.ReLU(inplace=True), - nn.Dropout(0.15), - nn.Linear(hidden, hidden), nn.BatchNorm1d(hidden), nn.ReLU(inplace=True), - nn.Dropout(0.15), - nn.Linear(hidden, hidden), nn.BatchNorm1d(hidden), nn.ReLU(inplace=True), - nn.Dropout(0.15), - nn.Linear(hidden, act_dim), - ) - def forward(self, obs, mask): - logits = self.net(obs) - logits[~mask] = -1e9 - return logits - - -# ── 动作常量 ────────────────────────────────────────────────────────────────── -WAIT, MOVE_UP, MOVE_DOWN, MOVE_LEFT, MOVE_RIGHT = 0, 1, 2, 3, 4 -BUY, HARVEST, DEPOSIT, LOAD, OCCUPY = 5, 11, 12, 18, 19 -SELL_0, SELL_1, SELL_2, SELL_3, SELL_4 = 6, 7, 8, 9, 10 -PRODUCE_0, PRODUCE_1, PRODUCE_2, PRODUCE_3, PRODUCE_4 = 13, 14, 15, 16, 17 -TECH_0, TECH_1, TECH_2, TECH_3, TECH_4, TECH_5, TECH_6, TECH_7 = range(20, 28) - -SELL_ACTIONS = [SELL_0, SELL_1, SELL_2, SELL_3, SELL_4] -PROD_ACTIONS = [PRODUCE_0, PRODUCE_1, PRODUCE_2, PRODUCE_3, PRODUCE_4] -TECH_ACTIONS = list(range(20, 28)) - -MOVE_DELTA = {MOVE_UP: (-1, 0), MOVE_DOWN: (1, 0), MOVE_LEFT: (0, -1), MOVE_RIGHT: (0, 1)} -MOVE_SET = {MOVE_UP, MOVE_DOWN, MOVE_LEFT, MOVE_RIGHT} - -# 科技名 → TECH_x 映射(用于按需购买) -TECH_KEY_TO_ID = { - "efficiency": TECH_1, - "path_optimization": TECH_5, - "durability": TECH_3, - "marketing": TECH_2, - "compute_expansion": TECH_7, -} - -# 科技购买优先级:路径优化→扩容→提价(path_opt 消除移动冷却最优先) -TECH_PRIORITY = ["efficiency", "path_optimization", "durability", "marketing"] - -PRODUCT = { - 0: {"cost": 10, "raw": 5, "lo": 40, "hi": 120, "time": 5.0}, - 1: {"cost": 5, "raw": 3, "lo": 20, "hi": 60, "time": 4.0}, - 2: {"cost": 1, "raw": 1, "lo": 4, "hi": 12, "time": 2.0}, - 3: {"cost": 8, "raw": 4, "lo": 32, "hi": 96, "time": 6.0}, - 4: {"cost": 3, "raw": 2, "lo": 12, "hi": 24, "time": 1.0}, -} - -# 观测索引 -OFF_X, OFF_Y, OFF_RAW, OFF_PROD = 0, 1, 3, 4 -OFF_BUSY, OFF_MONEY, OFF_COMP, OFF_TIME = 9, 10, 11, 12 -OFF_RES, OFF_CENTER, OFF_MARKET, OFF_TECH = 22, 34, 46, 74 - -CAP = 30.0 - - -def _price(pid, norm): - p = PRODUCT[pid] - rng = max(1.0, p["hi"] - p["lo"]) - return norm * rng + p["lo"] - - -class Agent(BaseAgent): - def __init__(self, env, mode="rule"): - super().__init__(env) - self.mode = mode - self.policy_net = None - - self.x = self.y = 0 - self.H = self.W = 0 - self._map_ok = False - - # 实体位置(obs 每步刷新) - self.mkts = {} # mid → (x, y) - self.res = {} # rid → (x, y) - self.ctrs = {} # cid → (x, y) - - # 经济 - self.money = 0.0 - self.compute = 0.0 - - # 记忆 - self._techs = set() - self._obs = set() # 已知障碍 - self._black = set() # 黑名单(不可达目标) - self._black_t = {} - self._cells = set() # 已访问 - self._fail = {} - - # 目标系统 - self._goal = None # (gx, gy) - self._goal_act = None # 到达后执行的动作 - self._goal_steps = 0 - self._goal_start_dist = 0 - self._state = "EXPLORE" - - # 卡住检测 - self._pos_hist = [] - - # Episode 检测 - self._last_t = -1.0 - self._eps_steps = 0 - - # 重规划 - self._replan = True - - # ── 新增:路径缓存 ── - self._path_cache = {} # (sx,sy,gx,gy) → [actions] or None - self._path_hits = 0 - self._path_misses = 0 - - # ── 新增:买入追踪 ── - self._last_buy_mid = None # 最近买入的市场 id - self._has_bought = False # 是否持有通过 BUY 获得的产品 - - # ── 新增:算力中心追踪 ── - self._occupied = set() # 已占领的算力中心 id - - # ── 新增:科技购买追踪(防止反复尝试)── - self._tech_attempted = {} # tech_key → fail_count - - # ═══════════════════════════════════════════════════════════════════════════ - # 观测 - # ═══════════════════════════════════════════════════════════════════════════ - - def _reset(self): - self._obs.clear() - self._black.clear() - self._black_t.clear() - self._cells.clear() - self._fail.clear() - self._pos_hist.clear() - self._techs.clear() - self._goal = None - self._goal_act = None - self._goal_steps = 0 - self._goal_start_dist = 0 - self._state = "EXPLORE" - self._replan = True - self._eps_steps = 0 - self._path_cache.clear() - self._last_buy_mid = None - self._has_bought = False - self._occupied.clear() - self._tech_attempted.clear() - - def _read_obs(self, obs): - # 地图检测 - if not self._map_ok: - m = 10 ** (obs[OFF_MONEY] * 5) - 1 - if m > 150: - self.H = self.W = 5 - elif m > 40: - self.H = self.W = 10 - else: - self.H = self.W = 15 - self._map_ok = True - - # Episode 重置检测 - t = obs[OFF_TIME] - if self._last_t >= 0 and t < self._last_t - 0.05: - self._reset() - self._last_t = t - self._eps_steps += 1 - - H, W = max(1, self.H), max(1, self.W) - - # 位置 - self.x = int(round(obs[OFF_X] * H)) - self.y = int(round(obs[OFF_Y] * W)) - - # 经济 - self.compute = obs[OFF_COMP] * 100.0 - self.money = 10 ** (obs[OFF_MONEY] * 5) - 1 - - # 资源 - self.res.clear() - for i in range(4): - b = OFF_RES + i * 3 - dx, dy = obs[b], obs[b + 1] - if abs(dx) + abs(dy) < 1e-6: - continue - rx = self.x + int(round(dx * H)) - ry = self.y + int(round(dy * W)) - if 0 <= rx < H and 0 <= ry < W: - self.res[i] = (rx, ry) - - # 中心 - self.ctrs.clear() - for i in range(3): - b = OFF_CENTER + i * 4 - dx, dy = obs[b], obs[b + 1] - if abs(dx) + abs(dy) < 1e-6: - continue - cx = self.x + int(round(dx * H)) - cy = self.y + int(round(dy * W)) - if 0 <= cx < H and 0 <= cy < W: - self.ctrs[i] = (cx, cy) - - # 市场 - self.mkts.clear() - for i in range(4): - b = OFF_MARKET + i * 7 - dx, dy = obs[b], obs[b + 1] - if abs(dx) + abs(dy) < 1e-6: - # 站在市场上:位置就是自身 - mx, my = self.x, self.y - else: - mx = self.x + int(round(dx * H)) - my = self.y + int(round(dy * W)) - if 0 <= mx < H and 0 <= my < W: - self.mkts[i] = (mx, my) - - # 检测新占领的算力中心 - self._check_new_centers(obs) - - # 更新买入追踪:如果身上没有产品了,清除标记 - if not self._has_prod(obs): - self._has_bought = False - self._last_buy_mid = None - - def _check_new_centers(self, obs): - """检测是否有新占领的算力中心。""" - for i in range(3): - b = OFF_CENTER + i * 4 - if b + 2 < len(obs) and obs[b + 2] > 0.5: - self._occupied.add(i) - - # ═══════════════════════════════════════════════════════════════════════════ - # 辅助 - # ═══════════════════════════════════════════════════════════════════════════ - - def _prices(self, obs, mid): - b = OFF_MARKET + mid * 7 + 2 - return {pid: _price(pid, obs[b + pid]) for pid in range(5)} - - def _all_prices(self, obs): - return {mid: self._prices(obs, mid) for mid in self.mkts} - - def _techs_owned(self, obs): - return [obs[OFF_TECH + i] > 0.5 for i in range(8)] - - def _busy(self, obs): - return obs[OFF_BUSY] * 10.0 > 0.5 - - def _has_raw(self, obs): - return obs[OFF_RAW] * CAP > 0.5 - - def _has_prod(self, obs): - return any(obs[OFF_PROD + i] * CAP > 0.01 for i in range(5)) - - def _raw_qty(self, obs): - return obs[OFF_RAW] * CAP - - def _prod_inv(self, obs): - return {pid: obs[OFF_PROD + pid] * CAP for pid in range(5) - if obs[OFF_PROD + pid] * CAP > 0.01} - - def _at_factory(self): - return self.x == 0 and self.y == 0 - - def _capacity(self, obs): - return 45.0 if self._techs_owned(obs)[3] else 30.0 - - # ═══════════════════════════════════════════════════════════════════════════ - # 障碍物学习 - # ═══════════════════════════════════════════════════════════════════════════ - - def _learn_obs(self, mask): - """标记被封堵的移动方向。""" - for act, (dx, dy) in MOVE_DELTA.items(): - if not mask[act]: - nx, ny = self.x + dx, self.y + dy - if 0 <= nx < self.H and 0 <= ny < self.W: - if (nx, ny) not in self._cells: - self._obs.add((nx, ny)) - - def _check_stuck(self): - self._pos_hist.append((self.x, self.y)) - if len(self._pos_hist) > 30: - self._pos_hist.pop(0) - if len(self._pos_hist) >= 25: - if len(set(self._pos_hist)) <= 3: - self._obs.clear() - self._black.clear() - self._black_t.clear() - self._pos_hist.clear() - self._path_cache.clear() - self._goal = None - self._goal_act = None - self._replan = True - - # ═══════════════════════════════════════════════════════════════════════════ - # A*(带缓存) - # ═══════════════════════════════════════════════════════════════════════════ - - def _astar(self, gx, gy): - if (self.x, self.y) == (gx, gy): - return [] - if not (0 <= gx < self.H and 0 <= gy < self.W): - return None - if (gx, gy) in self._obs: - return None - - # 检查缓存 - cache_key = (self.x, self.y, gx, gy) - if cache_key in self._path_cache: - self._path_hits += 1 - return self._path_cache[cache_key] - - self._path_misses += 1 - - start = (self.x, self.y) - goal = (gx, gy) - open_set = [(abs(start[0] - gx) + abs(start[1] - gy), 0, start, None, -1)] - came_from = {} - cost = {start: 0} - found = None - - while open_set: - _, c, pos, prev, act = heapq.heappop(open_set) - if pos in came_from: - continue - came_from[pos] = (prev, act) - if pos == goal: - found = pos - break - for a, (dx, dy) in MOVE_DELTA.items(): - nx, ny = pos[0] + dx, pos[1] + dy - if not (0 <= nx < self.H and 0 <= ny < self.W): - continue - if (nx, ny) in self._obs: - continue - nc = c + 1 - if (nx, ny) not in cost or nc < cost[(nx, ny)]: - cost[(nx, ny)] = nc - heapq.heappush(open_set, (nc + abs(nx - gx) + abs(ny - gy), nc, (nx, ny), pos, a)) - - if found is None: - self._path_cache[cache_key] = None - return None - - acts = [] - cur = found - while cur != start: - prev, a = came_from[cur] - acts.append(a) - cur = prev - acts.reverse() - - # 缓存路径(限制缓存大小) - if len(self._path_cache) < 5000: - self._path_cache[cache_key] = acts - - return acts - - # ═══════════════════════════════════════════════════════════════════════════ - # 目标超时检测 - # ═══════════════════════════════════════════════════════════════════════════ - - def _goal_timed_out(self): - if self._goal is None: - return False - gx, gy = self._goal - dist = abs(self.x - gx) + abs(self.y - gy) - - if self._goal_steps == 0: - self._goal_start_dist = dist - - self._goal_steps += 1 - timeout = 120 + self._goal_start_dist * 5 - - if self._goal_steps > timeout: - return True - if self._goal_steps > 40 and dist >= self._goal_start_dist: - return True - return False - - # ═══════════════════════════════════════════════════════════════════════════ - # 黑名单维护 - # ═══════════════════════════════════════════════════════════════════════════ - - def _blacklist_maintain(self): - expired = [p for p, t in self._black_t.items() if self._eps_steps - t > 800] - for p in expired: - self._black.discard(p) - del self._black_t[p] - while len(self._black) > 12: - old = min((p for p in self._black if p != (0, 0)), - key=lambda p: self._black_t.get(p, 0), default=None) - if old is None: - break - self._black.discard(old) - del self._black_t[old] - - def _blacklist(self, pos): - if pos and pos != (0, 0): - self._black.add(pos) - self._black_t[pos] = self._eps_steps - - # ═══════════════════════════════════════════════════════════════════════════ - # 导航 - # ═══════════════════════════════════════════════════════════════════════════ - - def _move_to(self, mask): - """向 _goal 移动一步。""" - if self._goal is None: - return None - gx, gy = self._goal - - # 已到达 - if (self.x, self.y) == (gx, gy): - return None - - # 超时检测 - if self._goal_timed_out(): - self._blacklist((gx, gy)) - self._goal = None - self._goal_act = None - return None - - # A* - path = self._astar(gx, gy) - if path and len(path) > 0 and mask[path[0]]: - return path[0] - - # 贪心兜底 - best, best_d = None, 999 - for a, (dx, dy) in MOVE_DELTA.items(): - if mask[a]: - nx, ny = self.x + dx, self.y + dy - if 0 <= nx < self.H and 0 <= ny < self.W: - d = abs(nx - gx) + abs(ny - gy) - if d < best_d: - best_d = d - best = a - - if best is None: - fc = self._fail.get((gx, gy), 0) + 1 - self._fail[(gx, gy)] = fc - if fc >= 3: - self._blacklist((gx, gy)) - self._fail.pop((gx, gy), None) - self._goal = None - self._goal_act = None - return best - - def _set_goal(self, gx, gy, action=None): - """设置新目标并重置计时器。""" - self._goal = (gx, gy) if gx is not None else None - self._goal_act = action - self._goal_steps = 0 - if gx is not None: - self._goal_start_dist = abs(self.x - gx) + abs(self.y - gy) - self._replan = False - - # ═══════════════════════════════════════════════════════════════════════════ - # 探索(BFS 最近未访问格) - # ═══════════════════════════════════════════════════════════════════════════ - - def _explore(self): - self._cells.add((self.x, self.y)) - q = deque([(self.x, self.y)]) - vis = {(self.x, self.y)} - while q: - cx, cy = q.popleft() - if (cx, cy) not in self._cells and (cx, cy) not in self._obs: - return (cx, cy) - for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: - nx, ny = cx + dx, cy + dy - if 0 <= nx < self.H and 0 <= ny < self.W and (nx, ny) not in vis: - vis.add((nx, ny)) - q.append((nx, ny)) - return None - - # ═══════════════════════════════════════════════════════════════════════════ - # 套利系统(核心) - # ═══════════════════════════════════════════════════════════════════════════ - - def _best_arbitrage(self, obs): - """找最佳套利机会。(buy_mid, sell_mid, pid, margin, profit_est) 或 None。""" - if len(self.mkts) < 2: - return None - prices = self._all_prices(obs) - - best = None - best_score = float("-inf") - - for bmid, bp in prices.items(): - bx, by = self.mkts[bmid] - if (bx, by) in self._black: - continue - for smid, sp in prices.items(): - if bmid == smid: - continue - sx, sy = self.mkts[smid] - if (sx, sy) in self._black: - continue - for pid in range(5): - buy_p = bp.get(pid, 0) - sell_p = sp.get(pid, 0) - if buy_p <= 0 or sell_p <= buy_p * 1.02: - continue - margin = sell_p - buy_p - # 综合评分:利润率 - 距离惩罚 - profit_rate = margin / max(buy_p, 1) - travel = abs(self.x - bx) + abs(self.y - by) + abs(bx - sx) + abs(by - sy) - # 有效的单步利润率(travel cost per unit is amortized over capacity) - cap = self._capacity(obs) - # 能买多少单位 - affordable = int(self.money / max(buy_p, 1)) if self.money > 0 else 0 - units = min(affordable, int(cap)) - if units <= 0: - continue - total_profit = units * margin - # 评分:单步期望收益(buy: units*2 tick, sell: 一次卖全部仅2 tick) - steps_est = travel + units * 2 + 2 - if steps_est <= 0: - continue - score = total_profit / steps_est - if score > best_score: - best_score = score - best = (bmid, smid, pid, margin, total_profit, buy_p, sell_p, units) - - return best - - def _best_sell_market(self, obs, avoid_mid=None): - """为身上产品找到最佳卖出市场。""" - prod_inv = self._prod_inv(obs) - if not prod_inv: - return None - - prices = self._all_prices(obs) - best = None - best_total = 0 - - for mid, mp in prices.items(): - if mid == avoid_mid: - continue - mx, my = self.mkts[mid] - if (mx, my) in self._black: - continue - total = 0 - sellable = 0 - for pid, qty in prod_inv.items(): - price = mp.get(pid, 0) - if price > 0: - total += qty * price - sellable += qty - if sellable > 0 and total > best_total: - best_total = total - d = abs(self.x - mx) + abs(self.y - my) - best = (mid, total, sellable, d) - - return best - - # ═══════════════════════════════════════════════════════════════════════════ - # 算力中心与科技 - # ═══════════════════════════════════════════════════════════════════════════ - - def _nearest_closed_center(self): - """返回最近的未占领算力中心。""" - best_cid = None - best_d = 999 - for cid, (cx, cy) in self.ctrs.items(): - if cid in self._occupied: - continue - if (cx, cy) in self._black: - continue - path = self._astar(cx, cy) - if path is None: - self._blacklist((cx, cy)) - continue - d = abs(self.x - cx) + abs(self.y - cy) - if d < best_d: - best_d = d - best_cid = cid - return best_cid - - def _next_tech_to_buy(self, obs): - """返回下一个应该购买的科技 TECH_x ID(mask 已检查),或 None。""" - techs = self._techs_owned(obs) - for key in TECH_PRIORITY: - tid = TECH_KEY_TO_ID[key] - idx = tid - TECH_0 - if techs[idx]: - continue # 已拥有 - # 检查失败次数(避免死循环) - fails = self._tech_attempted.get(key, 0) - if fails >= 5: - continue - return tid - return None - - def _should_get_techs(self, obs, mask): - """判断是否应该去工厂买科技。""" - # 已经有 path_optimization → 不需要 - techs = self._techs_owned(obs) - if techs[5] and techs[3]: - return False - if self._tech_attempted.get("path_optimization", 0) >= 5: - return False - # 在工厂且 mask 允许科技购买 - if not self._at_factory(): - return False - tid = self._next_tech_to_buy(obs) - if tid is None or not mask[tid]: - return False - return True - - # ═══════════════════════════════════════════════════════════════════════════ - # 主策略 - # ═══════════════════════════════════════════════════════════════════════════ - - def _plan(self, obs, mask): - self._blacklist_maintain() - - techs = self._techs_owned(obs) - has_prod = self._has_prod(obs) - prod_inv = self._prod_inv(obs) - prod_qty = sum(prod_inv.values()) - has_path_opt = techs[5] - cap = self._capacity(obs) - - # 站哪个市场旁? - at_mid = self._which_market_adjacent() - - # ═══════════════════════════════════════════════════════════════════════ - # P0: 在买入市场 → 继续批量买入(直到满了或没钱了再走) - # ═══════════════════════════════════════════════════════════════════════ - if has_prod and at_mid is not None and at_mid == self._last_buy_mid: - # 在买入市场,检查能否继续买 - if mask[BUY] and prod_qty < cap and self.money >= 1.0: - self._state = "ARB_BUY" - self._set_goal(None, None, BUY) - return - - # ═══════════════════════════════════════════════════════════════════════ - # P1: 在非买入市场旁 → 卖出手持产品 - # ═══════════════════════════════════════════════════════════════════════ - if has_prod and at_mid is not None and at_mid != self._last_buy_mid: - for pid in list(prod_inv.keys()): - if mask[SELL_0 + pid]: - self._state = "SELL" - self._set_goal(None, None, SELL_0 + pid) - return - best_sell = self._best_sell_market(obs, avoid_mid=self._last_buy_mid) - if best_sell: - self._state = "GO_SELL" - self._set_goal(*self.mkts[best_sell[0]], None) - return - - # ═══════════════════════════════════════════════════════════════════════ - # P1.5: 在工厂 → 买科技或等待算力 - # ═══════════════════════════════════════════════════════════════════════ - if self._at_factory(): - tid = self._next_tech_to_buy(obs) - if tid is not None and mask[tid]: - self._state = "TECH" - self._set_goal(None, None, tid) - return - # 还需要科技但算力不够→在工厂等待算力积累(避免第二趟往返) - if tid is not None and self._occupied and not has_prod: - self._state = "WAIT_COMPUTE" - self._goal = None - self._goal_act = None - return - - # ═══════════════════════════════════════════════════════════════════════ - # P2: 需要核心科技且有足够算力 → 回工厂(仅一次) - # ═══════════════════════════════════════════════════════════════════════ - need_tech = (not techs[1]) or (not techs[5]) or (not techs[3]) - if need_tech and self.compute >= 90 and not self._at_factory(): - path = self._astar(0, 0) - if path is not None and len(path) <= 20: - self._state = "GO_FACTORY" - self._set_goal(0, 0, None) - return - - # ═══════════════════════════════════════════════════════════════════════ - # P3: 有产品但不在市场 → 去最佳卖出市场 - # ═══════════════════════════════════════════════════════════════════════ - if has_prod and at_mid is None: - avoid = self._last_buy_mid if self._has_bought else None - best_sell = self._best_sell_market(obs, avoid_mid=avoid) - if best_sell: - self._state = "GO_SELL" - self._set_goal(*self.mkts[best_sell[0]], None) - return - - # ═══════════════════════════════════════════════════════════════════════ - # P3: 在市场旁且空手 → 开始批量买入 - # ═══════════════════════════════════════════════════════════════════════ - if not has_prod and at_mid is not None and mask[BUY] and self.money >= 1.0: - self._state = "ARB_BUY" - self._last_buy_mid = at_mid - self._has_bought = True - self._set_goal(None, None, BUY) - return - - # ═══════════════════════════════════════════════════════════════════════ - # P4: 未占领任何中心 → 主动去最近的计算中心(开局最关键!) - # ═══════════════════════════════════════════════════════════════════════ - if not self._occupied and self.ctrs and not has_prod: - cid = self._nearest_closed_center() - if cid is not None: - path = self._astar(*self.ctrs[cid]) - if path is not None: - self._state = "GO_CTR" - self._set_goal(*self.ctrs[cid], None) - return - - # ═══════════════════════════════════════════════════════════════════════ - # P6: 空手 → 找最佳套利对 → 去买入市场 - # ═══════════════════════════════════════════════════════════════════════ - if not has_prod and len(self.mkts) >= 2: - arb = self._best_arbitrage(obs) - if arb and arb[4] > 2: # 降低门槛,微小利润也能积累 - bmid = arb[0] - bx, by = self.mkts[bmid] - self._state = "ARB_GO_BUY" - self._set_goal(bx, by, None) - return - - # ═══════════════════════════════════════════════════════════════════════ - # P7: 有产品但没找到卖点 → 去最近非买入市场(兜底) - # ═══════════════════════════════════════════════════════════════════════ - if has_prod and self.mkts: - best_mid = None - best_d = 999 - for mid, (mx, my) in self.mkts.items(): - if mid == self._last_buy_mid: - continue - if (mx, my) in self._black: - continue - d = abs(self.x - mx) + abs(self.y - my) - if d < best_d: - best_d = d - best_mid = mid - if best_mid is not None: - self._state = "GO_SELL" - self._set_goal(*self.mkts[best_mid], None) - return - - # ═══════════════════════════════════════════════════════════════════════ - # P8: 探索/去最近市场 - # ═══════════════════════════════════════════════════════════════════════ - if self.mkts: - best_mid = None - best_score = -999 - for mid, (mx, my) in self.mkts.items(): - if (mx, my) in self._black: - continue - d = max(1, abs(self.x - mx) + abs(self.y - my)) - score = 50.0 / d - if score > best_score: - best_score = score - best_mid = mid - if best_mid is not None: - self._state = "GO_MKT" - self._set_goal(*self.mkts[best_mid], None) - return - - # ═══════════════════════════════════════════════════════════════════════ - # P11: 探索未知区域 - # ═══════════════════════════════════════════════════════════════════════ - ep = self._explore() - if ep: - self._state = "EXPLORE" - self._set_goal(*ep, None) - return - - self._state = "IDLE" - self._goal = None - - def _which_market_adjacent(self): - """返回当前相邻的市场 id。""" - for mid, (mx, my) in self.mkts.items(): - if abs(self.x - mx) + abs(self.y - my) <= 1: - return mid - return None - - # ═══════════════════════════════════════════════════════════════════════════ - # 主入口 - # ═══════════════════════════════════════════════════════════════════════════ - - def get_action(self, observation): - mask = self.env.action_masks() - - if self.mode == "rl" and self.policy_net is not None: - self._read_obs(observation) - self._check_stuck() - if self._busy(observation): - return WAIT - device = next(self.policy_net.parameters()).device - ot = torch.tensor(observation, dtype=torch.float32, device=device).unsqueeze(0) - mt = torch.tensor(mask, dtype=torch.bool, device=device).unsqueeze(0) - with torch.no_grad(): - return int(self.policy_net(ot, mt).argmax(dim=1).item()) - - # 规则模式 - valid = np.where(mask)[0] - self._read_obs(observation) - self._check_stuck() - - if self._busy(observation): - return WAIT - - # 只在非 busy 时学习障碍物 - self._learn_obs(mask) - - # ══ OCCUPY:最多占2个中心加速算力 ══ - if mask[OCCUPY] and len(self._occupied) < 2: - self._state = "OCCUPY" - self._set_goal(None, None, OCCUPY) - self._replan = False - self._goal_act = OCCUPY - - # 需要 replan? - if self._goal_act is not None: - if not mask[self._goal_act]: - # 动作不再可用 - key = None - for k, v in TECH_KEY_TO_ID.items(): - if v == self._goal_act: - key = k - break - if key: - self._tech_attempted[key] = self._tech_attempted.get(key, 0) + 1 - self._plan(observation, mask) - elif self._replan or self._goal is None: - self._plan(observation, mask) - elif self._goal is not None and (self.x, self.y) == self._goal: - self._plan(observation, mask) - - # 执行动作 - if self._goal_act is not None and mask[self._goal_act]: - a = self._goal_act - self._goal_act = None - self._replan = True - elif self._goal is not None: - a = self._move_to(mask) - if a is None: - if (self.x, self.y) == self._goal: - # 到达目标但没本地动作 → replan - pass - self._goal = None - self._replan = True - a = (list(set(valid) & MOVE_SET) or [WAIT])[0] - else: - # 无目标,尝试移动或等待 - a = (list(set(valid) & MOVE_SET) or [WAIT])[0] - - if a is None: - a = WAIT - self._cells.add((self.x, self.y)) - return a - - # ═══════════════════════════════════════════════════════════════════════════ - # 训练 + 持久化 - # ═══════════════════════════════════════════════════════════════════════════ - - def train(self, total_timesteps=50000, save_dir="submission/", eval_freq=4096, **kwargs): - os.makedirs(save_dir, exist_ok=True) - scores = [] - best = -float("inf") - obs = self.reset() - for t in range(total_timesteps): - a = self.get_action(obs) - obs, r, term, trunc, info = self.step(a) - if term or trunc: - scores.append(info.get("score", 0)) - obs = self.reset() - if (t + 1) % eval_freq == 0 and len(scores) >= 3: - m = np.mean(scores[-3:]) - if m > best: - best = m - self.save(os.path.join(save_dir, "model_best.pt")) - self.save(os.path.join(save_dir, "model_final.pt")) - return {"total_timesteps": total_timesteps, "episodes": len(scores), - "mean_score_last10": np.mean(scores[-10:]) if scores else 0, - "best_mean_score": best} - - def save(self, path): - d = {"mode": self.mode} - if self.policy_net is not None: - d["policy_net"] = self.policy_net.state_dict() - torch.save(d, path) - - @classmethod - def load(cls, path, env): - d = torch.load(path, map_location="cpu", weights_only=False) - a = cls(env, mode=d.get("mode", "rule")) - if "policy_net" in d: - a.policy_net = PolicyNet() - a.policy_net.load_state_dict(d["policy_net"]) - a.policy_net.eval() - a.policy_net.to("cuda" if torch.cuda.is_available() else "cpu") - a.mode = "rl" - return a diff --git a/logic/pve/submission/model.pt b/logic/pve/submission/model.pt deleted file mode 100644 index 7b1fa412a438154e6c868792244e701e5b9a7de4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1249 zcmWIWW@cev;NW1u0DKH047vF!sX6*7i6x181=%@nP67;3XrO_qwvZtLXarboAtRVs zRGO1o$W*Ks;LXmVGTHOJEKnMR18`a<%Af$XOfN0JC^xYrzAUwCU=xWJeTWcS5+>7j)EFT-F0ivUoP(l1Ue$^^zhRbmM+qT@4D+?)(Zc8Y)h7diQfqUrHj#Fj6hLDac8HAH|d) zVAg;*1fKNJH6zC%FN)@CaLv#(gRT`hU}aFW1_1*Z8UR?MJiwccO$Vw&j#(G37nF!W n07kcivNjO>07n`q`q