def __init__(self, width, height, order="C"): self._key_color = None self._ch = np.full((height, width), 0x20, dtype=np.intc) self._fg = np.zeros((height, width), dtype="(3,)u1") self._bg = np.zeros((height, width), dtype="(3,)u1") self._order = tcod._internal.verify_order(order) # libtcod uses the root console for defaults. bkgnd_flag = alignment = 0 if lib.TCOD_ctx.root != ffi.NULL: bkgnd_flag = lib.TCOD_ctx.root.bkgnd_flag alignment = lib.TCOD_ctx.root.alignment self._console_data = self.console_c = ffi.new( "struct TCOD_Console*", { "w": width, "h": height, "ch_array": ffi.cast("int*", self._ch.ctypes.data), "fg_array": ffi.cast("TCOD_color_t*", self._fg.ctypes.data), "bg_array": ffi.cast("TCOD_color_t*", self._bg.ctypes.data), "bkgnd_flag": bkgnd_flag, "alignment": alignment, "fore": (255, 255, 255), "back": (0, 0, 0), }, )
def sample_mgrid(self, mgrid): """Sample a mesh-grid array and return the result. The :any:`sample_ogrid` method performs better as there is a lot of overhead when working with large mesh-grids. Args: mgrid (numpy.ndarray): A mesh-grid array of points to sample. A contiguous array of type `numpy.float32` is preferred. Returns: numpy.ndarray: An array of sampled points. This array has the shape: ``mgrid.shape[:-1]``. The ``dtype`` is `numpy.float32`. """ mgrid = np.ascontiguousarray(mgrid, np.float32) if mgrid.shape[0] != self.dimensions: raise ValueError('mgrid.shape[0] must equal self.dimensions, ' '%r[0] != %r' % (mgrid.shape, self.dimensions)) out = np.ndarray(mgrid.shape[1:], np.float32) if mgrid.shape[1:] != out.shape: raise ValueError('mgrid.shape[1:] must equal out.shape, ' '%r[1:] != %r' % (mgrid.shape, out.shape)) lib.NoiseSampleMeshGrid(self._tdl_noise_c, out.size, ffi.cast('float*', mgrid.ctypes.data), ffi.cast('float*', out.ctypes.data)) return out
def sample_ogrid(self, ogrid): """Sample an open mesh-grid array and return the result. Args ogrid (Sequence[Sequence[float]]): An open mesh-grid. Returns: numpy.ndarray: An array of sampled points. The ``shape`` is based on the lengths of the open mesh-grid arrays. The ``dtype`` is `numpy.float32`. """ if len(ogrid) != self.dimensions: raise ValueError('len(ogrid) must equal self.dimensions, ' '%r != %r' % (len(ogrid), self.dimensions)) ogrids = [np.ascontiguousarray(array, np.float32) for array in ogrid] out = np.ndarray([array.size for array in ogrids], np.float32) lib.NoiseSampleOpenMeshGrid( self._tdl_noise_c, len(ogrids), out.shape, [ffi.cast('float*', array.ctypes.data) for array in ogrids], ffi.cast('float*', out.ctypes.data), ) return out
def __init__(self, width, height, order='C'): self._key_color = None self._ch = np.zeros((height, width), dtype=np.intc) self._fg = np.zeros((height, width), dtype='(3,)u1') self._bg = np.zeros((height, width), dtype='(3,)u1') self._order = tcod._internal.verify_order(order) # libtcod uses the root console for defaults. bkgnd_flag = alignment = 0 if lib.TCOD_ctx.root != ffi.NULL: bkgnd_flag = lib.TCOD_ctx.root.bkgnd_flag alignment = lib.TCOD_ctx.root.alignment self._console_data = self.console_c = ffi.new( 'struct TCOD_Console*', { 'w': width, 'h': height, 'ch_array': ffi.cast('int*', self._ch.ctypes.data), 'fg_array': ffi.cast('TCOD_color_t*', self._fg.ctypes.data), 'bg_array': ffi.cast('TCOD_color_t*', self._bg.ctypes.data), 'bkgnd_flag': bkgnd_flag, 'alignment': alignment, 'fore': (255, 255, 255), 'back': (0, 0, 0), }, )
def __setstate__(self, state): self._key_color = None self.__dict__.update(state) self._console_data.update( { 'ch_array': ffi.cast('int*', self._ch.ctypes.data), 'fg_array': ffi.cast('TCOD_color_t*', self._fg.ctypes.data), 'bg_array': ffi.cast('TCOD_color_t*', self._bg.ctypes.data), } ) self._console_data = self.console_c = ffi.new( 'struct TCOD_Console*', self._console_data)
def __setstate__(self, state): self._key_color = None self.__dict__.update(state) self._console_data.update( { "ch_array": ffi.cast("int*", self._ch.ctypes.data), "fg_array": ffi.cast("TCOD_color_t*", self._fg.ctypes.data), "bg_array": ffi.cast("TCOD_color_t*", self._bg.ctypes.data), } ) self._console_data = self.console_c = ffi.new( "struct TCOD_Console*", self._console_data )
def __as_cdata(self): return ffi.new('map_t *', ( self.width, self.height, self.width * self.height, ffi.cast('cell_t*', self.__buffer.ctypes.data), ))
def __init__( self, dimensions: int, algorithm: int = 2, implementation: int = SIMPLE, hurst: float = 0.5, lacunarity: float = 2.0, octaves: float = 4, seed: Optional[tcod.random.Random] = None, ): if not 0 < dimensions <= 4: raise ValueError("dimensions must be in range 0 < n <= 4, got %r" % (dimensions, )) self._random = seed _random_c = seed.random_c if seed else ffi.NULL self._algorithm = algorithm self.noise_c = ffi.gc( ffi.cast( "struct TCOD_Noise*", lib.TCOD_noise_new(dimensions, hurst, lacunarity, _random_c), ), lib.TCOD_noise_delete, ) self._tdl_noise_c = ffi.new("TDLNoise*", (self.noise_c, dimensions, 0, octaves)) self.implementation = implementation # sanity check
def __as_cdata(self): return ffi.new('struct TCOD_Map*', ( self.width, self.height, self.width * self.height, ffi.cast('struct TCOD_MapCell*', self.__buffer.ctypes.data), ))
def _init_setup_console_data(self, order="C"): """Setup numpy arrays over libtcod data buffers.""" global _root_console self._key_color = None if self.console_c == ffi.NULL: _root_console = self self._console_data = lib.TCOD_ctx.root else: self._console_data = ffi.cast( "struct TCOD_Console*", self.console_c ) def unpack_color(color_data): """return a (height, width, 3) shaped array from an image struct""" color_buffer = ffi.buffer(color_data[0 : self.width * self.height]) array = np.frombuffer(color_buffer, np.uint8) return array.reshape((self.height, self.width, 3)) self._fg = unpack_color(self._console_data.fg_array) self._bg = unpack_color(self._console_data.bg_array) buf = self._console_data.ch_array buf = ffi.buffer(buf[0 : self.width * self.height]) self._ch = np.frombuffer(buf, np.intc).reshape( (self.height, self.width) ) self._order = tcod._internal.verify_order(order)
def _init_setup_console_data(self, order='C'): """Setup numpy arrays over libtcod data buffers.""" self._key_color = None if self.console_c == ffi.NULL: self._console_data = lib.TCOD_ctx.root else: self._console_data = ffi.cast('TCOD_console_data_t *', self.console_c) def unpack_color(color_data): """return a (height, width, 3) shaped array from an image struct""" color_buffer = ffi.buffer(color_data[0:self.width * self.height]) array = np.frombuffer(color_buffer, np.uint8) return array.reshape((self.height, self.width, 3)) self._fg = unpack_color(self._console_data.fg_array) self._bg = unpack_color(self._console_data.bg_array) buf = self._console_data.ch_array buf = ffi.buffer(buf[0:self.width * self.height]) self._ch = np.frombuffer(buf, np.intc).reshape( (self.height, self.width)) order = tcod._internal.verify_order(order) if order == 'F': self._fg = self._fg.transpose(1, 0, 2) self._bg = self._bg.transpose(1, 0, 2) self._ch = self._ch.transpose()
def __init__(self, algorithm, seed=None): """Create a new instance using this algorithm and seed.""" if seed is None: seed = random.getrandbits(32) self.random_c = ffi.gc( ffi.cast('mersenne_data_t*', lib.TCOD_random_new_from_seed(algorithm, hash(seed) % (1 << 32))), lib.TCOD_random_delete)
def __init__( self, width: int, height: int, order: str = "C", buffer: Optional[np.array] = None, ): self._key_color = None # type: Optional[Tuple[int, int, int]] self._order = tcod._internal.verify_order(order) if buffer is not None: if self._order == "F": buffer = buffer.transpose() self._ch = np.ascontiguousarray(buffer["ch"], np.intc) self._fg = np.ascontiguousarray(buffer["fg"], "u1") self._bg = np.ascontiguousarray(buffer["bg"], "u1") else: self._ch = np.ndarray((height, width), dtype=np.intc) self._fg = np.ndarray((height, width), dtype=self._DTYPE_RGB) self._bg = np.ndarray((height, width), dtype=self._DTYPE_RGB) # libtcod uses the root console for defaults. default_bg_blend = 0 default_alignment = 0 if lib.TCOD_ctx.root != ffi.NULL: default_bg_blend = lib.TCOD_ctx.root.bkgnd_flag default_alignment = lib.TCOD_ctx.root.alignment self._console_data = self.console_c = ffi.new( "struct TCOD_Console*", { "w": width, "h": height, "ch_array": ffi.cast("int*", self._ch.ctypes.data), "fg_array": ffi.cast("TCOD_color_t*", self._fg.ctypes.data), "bg_array": ffi.cast("TCOD_color_t*", self._bg.ctypes.data), "bkgnd_flag": default_bg_blend, "alignment": default_alignment, "fore": (255, 255, 255), "back": (0, 0, 0), }, ) if buffer is None: self.clear()
def __as_cdata(self) -> Any: return ffi.new( "struct TCOD_Map*", ( self.width, self.height, self.width * self.height, ffi.cast("struct TCOD_MapCell*", self.__buffer.ctypes.data), ), )
def get_tcod_path_ffi(self) -> Tuple[Any, Any, Tuple[int, int]]: if len(self.shape) != 2: raise ValueError("Array must have a 2d shape, shape is %r" % (self.shape, )) if self.dtype.type not in self._C_ARRAY_CALLBACKS: raise ValueError("dtype must be one of %r, dtype is %r" % (self._C_ARRAY_CALLBACKS.keys(), self.dtype.type)) array_type, callback = self._C_ARRAY_CALLBACKS[self.dtype.type] userdata = ffi.new( "struct PathCostArray*", (ffi.cast("char*", self.ctypes.data), self.strides), ) return callback, userdata, self.shape
def get_tcod_path_ffi(self): if len(self.shape) != 2: raise ValueError('Array must have a 2d shape, shape is %r' % (self.shape, )) if self.dtype.type not in self._C_ARRAY_CALLBACKS: raise ValueError('dtype must be one of %r, dtype is %r' % (self._C_ARRAY_CALLBACKS.keys(), self.dtype.type)) array_type, callback = \ self._C_ARRAY_CALLBACKS[self.dtype.type] userdata = ffi.new( 'PathCostArray*', (self.width, ffi.cast(array_type, self.ctypes.data)), ) return callback, userdata, self.width, self.height
def get_tile(self, codepoint: int) -> np.array: """Return a copy of a tile for the given codepoint. If the tile does not exist yet then a blank array will be returned. The tile will have a shape of (height, width, rgba) and a dtype of uint8. Note that most grey-scale tiles will only use the alpha channel and will usually have a solid white color channel. """ tile = np.zeros(self.tile_shape + (4, ), dtype=np.uint8) lib.TCOD_tileset_get_tile_( self._tileset_p, codepoint, ffi.cast("struct TCOD_ColorRGBA*", tile.ctypes.data), ) return tile
def __init__( self, algorithm: int = MERSENNE_TWISTER, seed: Optional[Hashable] = None, ): """Create a new instance using this algorithm and seed.""" if seed is None: seed = random.getrandbits(32) self.random_c = ffi.gc( ffi.cast( "mersenne_data_t*", lib.TCOD_random_new_from_seed(algorithm, hash(seed) % (1 << 32)), ), lib.TCOD_random_delete, )
def _init_setup_console_data(self, order: str = "C") -> None: """Setup numpy arrays over libtcod data buffers.""" global _root_console self._key_color = None if self.console_c == ffi.NULL: _root_console = self self._console_data = lib.TCOD_ctx.root else: self._console_data = ffi.cast("struct TCOD_Console*", self.console_c) self._tiles = np.frombuffer( ffi.buffer(self._console_data.tiles[0:self.width * self.height]), dtype=self.DTYPE, ).reshape((self.height, self.width)) self._order = tcod._internal.verify_order(order)
def __setstate__(self, state: Any) -> None: self._key_color = None if "_tiles" not in state: tiles = np.ndarray((self.height, self.width), dtype=self.DTYPE) tiles["ch"] = state["_ch"] tiles["fg"][..., :3] = state["_fg"] tiles["fg"][..., 3] = 255 tiles["bg"][..., :3] = state["_bg"] tiles["bg"][..., 3] = 255 state["_tiles"] = tiles del state["_ch"] del state["_fg"] del state["_bg"] self.__dict__.update(state) self._console_data["tiles"] = ffi.cast("struct TCOD_ConsoleTile*", self._tiles.ctypes.data) self._console_data = self.console_c = ffi.new("struct TCOD_Console*", self._console_data)
def __init__(self, dimensions, algorithm=2, implementation=SIMPLE, hurst=0.5, lacunarity=2.0, octaves=4, seed=None): if not 0 < dimensions <= 4: raise ValueError('dimensions must be in range 0 < n <= 4, got %r' % (dimensions,)) self._random = seed _random_c = seed.random_c if seed else ffi.NULL self._algorithm = algorithm self.noise_c = ffi.gc( ffi.cast( 'perlin_data_t*', lib.TCOD_noise_new(dimensions, hurst, lacunarity, _random_c), ), lib.TCOD_noise_delete) self._tdl_noise_c = ffi.new('TDLNoise*', (self.noise_c, dimensions, 0, octaves)) self.implementation = implementation # sanity check
def set_tile(self, codepoint: int, tile: np.array) -> None: """Upload a tile into this array. The tile can be in 32-bit color (height, width, rgba), or grey-scale (height, width). The tile should have a dtype of ``np.uint8``. This data may need to be sent to graphics card memory, this is a slow operation. """ tile = np.ascontiguousarray(tile, dtype=np.uint8) if tile.shape == self.tile_shape: full_tile = np.empty(self.tile_shape + (4, ), dtype=np.uint8) full_tile[:, :, :3] = 255 full_tile[:, :, 3] = tile return self.set_tile(codepoint, full_tile) required = self.tile_shape + (4, ) if tile.shape != required: raise ValueError("Tile shape must be %r or %r, got %r." % (required, self.tile_shape, tile.shape)) lib.TCOD_tileset_set_tile_( self._tileset_p, codepoint, ffi.cast("struct TCOD_ColorRGBA*", tile.ctypes.data), )
def _get_pathcost_func( name: str) -> Callable[[int, int, int, int, Any], float]: """Return a properly cast PathCostArray callback.""" return ffi.cast( # type: ignore "TCOD_path_func_t", ffi.addressof(lib, name))
def _get_pathcost_func(name): """Return a properly cast PathCostArray callback.""" return ffi.cast('TCOD_path_func_t', ffi.addressof(lib, name))
def _get_pathcost_func(name): # type: (str) -> Callable[[int, int, int, int, cffi.CData], float] """Return a properly cast PathCostArray callback.""" return ffi.cast("TCOD_path_func_t", ffi.addressof(lib, name))