mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Update MapMerge2
This commit is contained in:
12
tools/mapmerge2/Prepare Maps.bat
Normal file
12
tools/mapmerge2/Prepare Maps.bat
Normal file
@@ -0,0 +1,12 @@
|
||||
@echo off
|
||||
cd ../../_maps/
|
||||
|
||||
for /R %%f in (*.dmm) do copy "%%f" "%%f.backup"
|
||||
|
||||
cls
|
||||
echo All dmm files in _maps directories have been backed up
|
||||
echo Now you can make your changes...
|
||||
echo ---
|
||||
echo Remember to run mapmerge.bat just before you commit your changes!
|
||||
echo ---
|
||||
pause
|
||||
@@ -31,10 +31,12 @@ class DMM:
|
||||
return _parse(bytes.decode(ENCODING))
|
||||
|
||||
def to_file(self, fname, tgm = True):
|
||||
self._presave_checks()
|
||||
with open(fname, 'w', newline='\n', encoding=ENCODING) as f:
|
||||
(save_tgm if tgm else save_dmm)(self, f)
|
||||
|
||||
def to_bytes(self, tgm = True):
|
||||
self._presave_checks()
|
||||
bio = io.BytesIO()
|
||||
with io.TextIOWrapper(bio, newline='\n', encoding=ENCODING) as f:
|
||||
(save_tgm if tgm else save_dmm)(self, f)
|
||||
@@ -42,12 +44,7 @@ class DMM:
|
||||
return bio.getvalue()
|
||||
|
||||
def generate_new_key(self):
|
||||
# ensure that free keys exist by increasing the key length if necessary
|
||||
free_keys = (BASE ** self.key_length) - len(self.dictionary)
|
||||
while free_keys <= 0:
|
||||
self.key_length += 1
|
||||
free_keys = (BASE ** self.key_length) - len(self.dictionary)
|
||||
|
||||
free_keys = self._ensure_free_keys(1)
|
||||
# choose one of the free keys at random
|
||||
key = 0
|
||||
while free_keys:
|
||||
@@ -61,6 +58,32 @@ class DMM:
|
||||
|
||||
raise RuntimeError("ran out of keys, this shouldn't happen")
|
||||
|
||||
def _presave_checks(self):
|
||||
# last-second handling of bogus keys to help prevent and fix broken maps
|
||||
self._ensure_free_keys(0)
|
||||
max_key = max_key_for(self.key_length)
|
||||
bad_keys = {key: 0 for key in self.dictionary.keys() if key > max_key}
|
||||
if bad_keys:
|
||||
print(f"Warning: fixing {len(bad_keys)} overflowing keys")
|
||||
for k in bad_keys:
|
||||
# create a new non-bogus key and transfer that value to it
|
||||
new_key = bad_keys[k] = self.generate_new_key()
|
||||
self.dictionary.forceput(new_key, self.dictionary[k])
|
||||
print(f" {num_to_key(k, self.key_length, True)} -> {num_to_key(new_key, self.key_length)}")
|
||||
for k, v in self.grid.items():
|
||||
# reassign the grid entries which used the old key
|
||||
self.grid[k] = bad_keys.get(v, v)
|
||||
|
||||
def _ensure_free_keys(self, desired):
|
||||
# ensure that free keys exist by increasing the key length if necessary
|
||||
free_keys = max_key_for(self.key_length) - len(self.dictionary)
|
||||
while free_keys < desired:
|
||||
if self.key_length >= MAX_KEY_LENGTH:
|
||||
raise KeyTooLarge(f"can't expand beyond key length {MAX_KEY_LENGTH} ({len(self.dictionary)} keys)")
|
||||
self.key_length += 1
|
||||
free_keys = max_key_for(self.key_length) - len(self.dictionary)
|
||||
return free_keys
|
||||
|
||||
@property
|
||||
def coords_zyx(self):
|
||||
for z in range(1, self.size.z + 1):
|
||||
@@ -82,6 +105,7 @@ class DMM:
|
||||
# key handling
|
||||
|
||||
# Base 52 a-z A-Z dictionary for fast conversion
|
||||
MAX_KEY_LENGTH = 3 # things will get ugly fast if you exceed this
|
||||
BASE = 52
|
||||
base52 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
base52_r = {x: i for i, x in enumerate(base52)}
|
||||
@@ -93,8 +117,8 @@ def key_to_num(key):
|
||||
num = BASE * num + base52_r[ch]
|
||||
return num
|
||||
|
||||
def num_to_key(num, key_length):
|
||||
if num >= BASE ** key_length:
|
||||
def num_to_key(num, key_length, allow_overflow=False):
|
||||
if num >= (BASE ** key_length if allow_overflow else max_key_for(key_length)):
|
||||
raise KeyTooLarge(f"num={num} does not fit in key_length={key_length}")
|
||||
|
||||
result = ''
|
||||
@@ -105,6 +129,11 @@ def num_to_key(num, key_length):
|
||||
assert len(result) <= key_length
|
||||
return base52[0] * (key_length - len(result)) + result
|
||||
|
||||
def max_key_for(key_length):
|
||||
# keys only go up to "ymo" = 65534, under-estimated just in case
|
||||
# https://secure.byond.com/forum/?post=2340796#comment23770802
|
||||
return min(65530, BASE ** key_length)
|
||||
|
||||
class KeyTooLarge(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
set MAPROOT=../../maps/tether
|
||||
set MAPROOT=../../_maps/
|
||||
set TGM=1
|
||||
python convert.py
|
||||
pause
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
set MAPROOT=../../maps/tether
|
||||
set MAPROOT=../../_maps/
|
||||
set TGM=1
|
||||
python mapmerge.py
|
||||
pause
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
set MAPROOT=../../maps/tether
|
||||
set MAPROOT=../../_maps/
|
||||
set TGM=0
|
||||
python convert.py
|
||||
pause
|
||||
|
||||
Reference in New Issue
Block a user