Patch for Atria to turn it into a map generation server
diff --git a/atria/core/server.py b/atria/core/server.py | |
index f85c091..0c180b2 100644 | |
--- a/atria/core/server.py | |
+++ b/atria/core/server.py | |
@@ -23,6 +23,7 @@ from .storage import STORES | |
from .timing import TIMERS | |
from .utils.exceptions import ServerReboot, ServerReload, ServerShutdown | |
from .utils.funcs import joins | |
+from .world import MapShell | |
log = get_logger("server") | |
@@ -255,7 +256,7 @@ def _hook_client_connected(client): | |
session = SESSIONS.create(client) | |
with EVENTS.fire("session_started", session): | |
session.send(SESSIONS.connect_greeting) | |
- session.menu = ConnectMenu | |
+ session.shell = MapShell | |
@EVENTS.hook("client_disconnected") | |
diff --git a/atria/core/world.py b/atria/core/world.py | |
index 4149676..9db118d 100644 | |
--- a/atria/core/world.py | |
+++ b/atria/core/world.py | |
@@ -4,12 +4,17 @@ | |
+import random | |
import re | |
from weakref import WeakSet | |
+from .commands import Command, COMMANDS | |
+from .const import * | |
from .entities import Attribute, ENTITIES, Entity, Unset | |
+from .events import EVENTS | |
from .logs import get_logger | |
from .pickle import PickleStore | |
+from .shells import Shell, SHELLS | |
from .storage import STORES | |
from .utils.funcs import joins | |
@@ -177,3 +182,133 @@ def get_movement_strings(change): | |
""" | |
return _movement_strings.get(change, ("nowhere", "nowhere")) | |
+ | |
+ | |
+@SHELLS.register | |
+class MapShell(Shell): | |
+ | |
+ state = STATE_PLAYING | |
+ | |
+ def init(self): | |
+ self.session.color = True | |
+ | |
+ | |
+@COMMANDS.register | |
+class MapGenCommand(Command): | |
+ | |
+ def _action(self): | |
+ m = Map() | |
+ m.generate_square(78, 40) | |
+ m.print_square(self.session, 78, 40) | |
+ | |
+ | |
+@EVENTS.hook("server_boot") | |
+def _hook_server_boot(): | |
+ from .cmds.cmd_basic import QuitCommand | |
+ MapShell.add_verbs(MapGenCommand, "mapgen") | |
+ MapShell.add_verbs(QuitCommand, "q", "quit", "logout", "done", "exit", truncate=False) | |
+ | |
+ | |
+# Coordinate deltas for each direction | |
+_DIRS = [(1,0),(1,-1),(0,-1),(-1,-1),(-1,0),(-1,1),(0,1),(1,1)] | |
+# east ne north nw west sw south se | |
+ | |
+ | |
+class _Tile: | |
+ | |
+ def __init__(self, x, y, map): | |
+ self._map = map | |
+ self.x = x | |
+ self.y = y | |
+ self.elevation = None | |
+ | |
+ def _get_neighbor(self, dir): | |
+ coord = (self.x + _DIRS[dir][0], self.y + _DIRS[dir][1]) | |
+ return self._map._tiles.get(coord) | |
+ | |
+ def choose_elevation(self, ignore_dirs = ()): | |
+ choices = [] | |
+ for n in range(8): | |
+ if n in ignore_dirs: | |
+ continue | |
+ tile = self._get_neighbor(n) | |
+ if tile: | |
+ threshold = self._map.ELEVATION_THRESHOLD | |
+ elevation_min = max(tile.elevation - threshold, self._map.MIN_ELEVATION) | |
+ elevation_max = min(tile.elevation + threshold, self._map.MAX_ELEVATION) | |
+ choices.extend(range(elevation_min, elevation_max + 1)) | |
+ choices.extend([tile.elevation] * self._map.NEIGHBOR_WEIGHT) | |
+ if choices: | |
+ self.elevation = random.choice(choices) | |
+ else: | |
+ self.elevation = self._map.base_elevation | |
+ | |
+ | |
+class Map: | |
+ | |
+ MIN_ELEVATION = -8 | |
+ MAX_ELEVATION = 12 | |
+ SEA_LEVEL = 0 | |
+ ELEVATION_THRESHOLD = 1 | |
+ NEIGHBOR_WEIGHT = 3 | |
+ | |
+ def __init__(self, base_elevation=4): | |
+ self._tiles = {} | |
+ self.base_elevation = max(self.MIN_ELEVATION, min(base_elevation, self.MAX_ELEVATION)) | |
+ | |
+ def _get_terrain_symbol(self, elevation): | |
+ #### adjust to be based on variables like SEA_LEVEL | |
+ if elevation is None: | |
+ return "^R!" | |
+ if elevation >= 12: | |
+ return '^k^^' | |
+ if elevation >= 10: | |
+ return "^K^^" | |
+ if elevation >= 9: | |
+ return '^yn' | |
+ if elevation >= 7: | |
+ return "^Yn" | |
+ if elevation >= 6: | |
+ return '^g"' | |
+ if elevation >= 3: | |
+ return '^G"' | |
+ if elevation >= 1: | |
+ return "^Y." | |
+ if elevation >= 0: | |
+ return "^y." | |
+ if elevation >= -3: | |
+ return '^C,' | |
+ if elevation >= -4: | |
+ return "^c," | |
+ if elevation >= -7: | |
+ return "^B~" | |
+ if elevation >= -8: | |
+ return "^b~" | |
+ return '^R?' | |
+ | |
+ def add_tile(self, x, y): | |
+ tile = _Tile(x, y, self) | |
+ self._tiles[(x, y)] = tile | |
+ return tile | |
+ | |
+ def generate_square(self, width=3, height=3): | |
+ max_x = width // 2 | |
+ max_y = height // 2 | |
+ for x in range(-max_x, max_x + (width % 2)): | |
+ for y in range(-max_y, max_y + (height % 2)): | |
+ if not (x, y) in self._tiles: | |
+ tile = self.add_tile(x, y) | |
+ tile.choose_elevation() | |
+ | |
+ def print_square(self, session, width=3, height=3, center = (0, 0)): | |
+ max_x = width // 2 | |
+ max_y = height // 2 | |
+ for y in range(center[1] - max_y, center[1] + max_y + (height % 2)): | |
+ row = [] | |
+ for x in range(center[0] - max_x, center[1] + max_x + (width % 2)): | |
+ tile = self._tiles.get((x, y)) | |
+ row.append(self._get_terrain_symbol(tile.elevation) if tile else " ") | |
+ session.send("".join(row)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment