Some work on blocks access

develop
RusAnon 2010-05-03 21:19:40 +11:00
parent add3288333
commit 394002f688
5 changed files with 193 additions and 43 deletions

@ -1,3 +1,12 @@
# -*- coding: utf-8 -*-
"""
Module for high-level abstraction of tiles
"""
from collections import namedtuple
from .pydftypes import Rectangle
from .mixins import NoStart
from .decorators import suspend
class Point(object):
x = None
y = None
@ -19,35 +28,112 @@ class Point(object):
def xyz(self):
return (self.x, self.y, self.z)
@property
def rect(self):
"""
Return block coords in form (x1, y1, x2, y2)
"""
block = self.get_block()
x1 = block.x * 16
y1 = block.y * 16
return Rectangle(x1, y1, x1+15, y1+15)
def __repr__(self):
b = ''
if self.block:
b = ', Block'
return "<Point({0.x}, {0.y}, {0.z}{1})>".format(self, b)
return "<Point(X:{0.x}, Y:{0.y}, Z:{0.z}{1})>".format(self, b)
class Block(object):
class Block(NoStart):
"""
16x16 tiles block
"""
api = None
tiles = None
coords = None
x1 = None
y1 = None
def __init__(self, api, coords):
"""
api is instance of API, which is used for read/write operations
coords is Point object
"""
self.api = api
if not isinstance(Point, coords):
if not isinstance(coords, Point):
raise Exception(u"coords parameter should be Point")
if not coords.block:
coords = coords.get_block()
self.coords = coords
self.rect = self.coords.rect
self.reload()
@suspend
def reload(self):
tile_types = self.api.maps.Read_Tile_Types(point=self.coords)
tile_flags = self.api.maps.Read_Designations(point=self.coords)
if self.tiles:
for x in range(16):
for y in range(16):
self.tiles[x][y].update(ttype=tile_types[x][y], flags=tile_flags[x][y])
else:
self.tiles = []
for x in range(16):
row = []
for y in range(16):
row.append(Tile(self, tile_types[x][y], tile_flags[x][y], self.rect.x1 + x, self.rect.y1 + y, self.coords.z))
self.tiles.append(row)
@suspend
def save(self):
tile_types = map(lambda x:range(16), range(16))
tile_flags = map(lambda x:range(16), range(16))
for x in range(16):
for y in range(16):
tile_types[x][y] = self.tiles[x][y].ttype
tile_flags[x][y] = self.tiles[x][y].flags
self.api.maps.Write_Tile_Types(point=self.coords, tiles=tile_types)
# Designations are bugged
#self.api.maps.Write_Designations(point=self.coords, tiles=tile_flags)
def get_tile(self, x=0, y=0, z=0, point=None):
if point:
x, y, z = point.xyz
if z == self.coords.z and (self.rect.y1 <= y <= self.rect.y2) and (self.rect.x1 <= x <= self.rect.x2):
return self.tiles[x%16][y%16]
else:
raise Exception("This tile does not belong to this block")
def __repr__(self):
return "<Block(X:{2}-{4}, Y:{3}-{5}, Z:{1.z})>".format(self, self.coords, *self.coords.rect)
class Tile(object):
coords = None
block = None
ttype = None
temperature = None
flags = None
def __init__(self, block, ttype, flags, x=0, y=0, z=0, point=None):
self.ttype = ttype
self.flags = flags
if not point:
point = Point(x, y, z)
self.coords = point
self.block = block
def update(self, ttype, flags):
self.ttype = ttype
self.flags = flags
def reload(self):
pass
self.block.reload()
def save(self):
pass
self.block.save()
def __repr__(self):
return "<Tile({0.ttype} at {1.x}, {1.y}, {1.z})>".format(self, self.coords)

@ -5,6 +5,7 @@ Python class for DF_Hack::Maps
from ._pydfhack import _MapManager
from .mixins import NeedsStart
from .decorators import suspend
from .blocks import Block, Point
class Map(NeedsStart, _MapManager):
api = None
@ -14,15 +15,18 @@ class Map(NeedsStart, _MapManager):
self.api = api
@suspend
def Write_Tile_Types(self, x=0, y=0, z=0, tiles=None, point=None):
def get_size(self):
return self.size
@suspend
def Is_Valid_Block(self, x=0, y=0, z=0, point=None):
"""
Checks if coords are valid
"""
if point:
point = point.get_block()
x, y, z = point.xyz
return self.cls.Write_Tile_Types(self, x, y, z, tiles)
@suspend
def Write_Occupancy(self, *args, **kw):
return self.cls.Write_Occupancy(self, *args, **kw)
return self.cls.Is_Valid_Block(self, x, y, z)
@suspend
def Read_Tile_Types(self, x=0, y=0, z=0, point=None):
@ -36,25 +40,42 @@ class Map(NeedsStart, _MapManager):
return self.cls.Read_Tile_Types(self, x, y, z)
@suspend
def Is_Valid_Block(self, *args, **kw):
return self.cls.Is_Valid_Block(self, *args, **kw)
def Write_Tile_Types(self, x=0, y=0, z=0, tiles=None, point=None):
if point:
point = point.get_block()
x, y, z = point.xyz
return self.cls.Write_Tile_Types(self, x, y, z, tiles)
@suspend
def Read_Designations(self, x=0, y=0, z=0, point=None):
"""
Returns 16x16 block in form of list of lists.
"""
if point:
point = point.get_block()
x, y, z = point.xyz
return self.cls.Read_Designations(self, x, y, z)
@suspend
def Write_Designations(self, x=0, y=0, z=0, tiles=None, point=None):
if point:
point = point.get_block()
x, y, z = point.xyz
return self.cls.Write_Designations(self, x, y, z, tiles)
@suspend
def Write_Occupancy(self, *args, **kw):
return self.cls.Write_Occupancy(self, *args, **kw)
@suspend
def Write_Dirty_Bit(self, *args, **kw):
return self.cls.Write_Dirty_Bit(self, *args, **kw)
@suspend
def Read_Designations(self, *args, **kw):
return self.cls.Read_Designations(self, *args, **kw)
@suspend
def Write_Block_Flags(self, *args, **kw):
return self.cls.Write_Block_Flags(self, *args, **kw)
@suspend
def Write_Designations(self, *args, **kw):
return self.cls.Write_Designations(self, *args, **kw)
@suspend
def Read_Region_Offsets(self, *args, **kw):
return self.cls.Read_Region_Offsets(self, *args, **kw)
@ -80,5 +101,16 @@ class Map(NeedsStart, _MapManager):
return self.cls.Read_Block_40d(self, *args, **kw)
@suspend
def get_size(self):
return self.size
def get_block(self, point):
point = point.get_block()
block = Block(api=self.api, coords=point)
return block
@suspend
def get_tile(self, x=0, y=0, z=0, point=None):
if not point:
point = Point(x, y, z)
block = Block(api=self.api, coords=point.get_block())
return block.get_tile(point=point)

@ -17,7 +17,10 @@ class Position(NoStart, _PositionManager):
@suspend
def get_cursor(self):
coords = self.cursor_coords
if coords:
return Point(*coords)
else:
return None
@suspend
def get_window_size(self):
@ -28,3 +31,12 @@ class Position(NoStart, _PositionManager):
def get_view_coords(self):
coords = self.view_coords
return Point(*coords)
@suspend
def get_cursor_tile(self):
point = self.get_cursor()
if point:
tile = self.api.maps.get_tile(point=point)
return tile
else:
return None

@ -1,4 +1,4 @@
import _pydfhack, os
import _pydfhack, os, copy
from .blocks import Point, Block
from .meminfo import MemInfo
from .position import Position
@ -44,9 +44,28 @@ class API(_pydfhack._API):
self._gui_mgr_type = GUI
self.started = []
def Attach(self, *args, **kw):
print "API.Attach()"
return _pydfhack._API.Attach(self, *args, **kw)
def Detach(self, *args, **kw):
print "API.Detach()"
return _pydfhack._API.Detach(self, *args, **kw)
def Suspend(self, *args, **kw):
print "API.Suspend()"
return _pydfhack._API.Suspend(self, *args, **kw)
def Resume(self):
# Explicitly Finish() all started modules
for m in self.started[:]:
m.Finish()
self.started = []
_pydfhack._API.Resume(self)
print "API.Resume()"
# Reference counting is fcked, so leave it alone for now
## Explicitly Finish() all started modules
#print self.started
#started = copy.copy(self.started)
#print started
#for m in started:
# print m
# m.Finish()
#self.started = []
return _pydfhack._API.Resume(self)

@ -1,24 +1,24 @@
#!/usr/bin/python
import sys
import pydfhack
from smarthttp.lib.containers import SmartDict
DF = pydfhack.API("Memory.xml")
DF.Attach()
pos = DF.position
maps = DF.maps
maps.Start()
cursor = pos.cursor_coords
msize = maps.size
block = SmartDict()
refc = dict(pydfhack=pydfhack, API=pydfhack.API, DF=DF, pos=pos, maps=maps)
cursor = pos.get_cursor()
msize = maps.get_size()
block = None
tile = None
if cursor:
block.coords = (cursor[0]/16, cursor[1]/16, cursor[2])
block.tiles = maps.Read_Tile_Types(block.coords[0], block.coords[1], block.coords[2])
maps.Finish()
block = maps.get_block(point=cursor)
if block:
tile = block.get_tile(point=cursor)
DF.Resume()
locs = dict(pydfhack=pydfhack, API=pydfhack.API, DF=DF, pos=pos, maps=maps, msize=msize, cursor=cursor, block=block)
locs = dict(pydfhack=pydfhack, API=pydfhack.API, DF=DF, pos=pos, maps=maps, msize=msize, cursor=cursor, block=block, tile=tile)
banner = """DFHack Shell\n\n"""\
"""\tpydfhack = {pydfhack}\n"""\
@ -28,10 +28,11 @@ banner = """DFHack Shell\n\n"""\
"""\tmaps = {maps}\n"""\
"""\tmsize = {msize}\n"""\
"""\tcursor = {cursor}\n"""\
"""\tblock = {block}\n""".format(**locs)
"""\tblock = {block}\n"""\
"""\ttile = {tile}\n""".format(**locs)
from IPython.Shell import IPShellEmbed
shell = IPShellEmbed()
shell.set_banner(shell.IP.BANNER + '\n\n' + banner)
shell(local_ns=locs, global_ns={})
DF.Detach()