Skip to content

Instantly share code, notes, and snippets.

@whutch whutch/mapgen.patch
Created Jan 14, 2016

Embed
What would you like to do?
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
You can’t perform that action at this time.