Package tdl |
[frames] | no frames]

# Source Code for Package tdl

       1  """
       2      This is the official documentation for python-tdl.  A Pythonic port of
       3      U{libtcod<http://roguecentral.org/doryen/libtcod/>}.
       4
       5      You can find the project page on GitHub
       6      U{here<https://github.com/HexDecimal/python-tdl>}.
       7
       8      Report any bugs or issues to the GitHub issue tracker
       9      U{here<https://github.com/HexDecimal/python-tdl/issues>}.
      10
      11      Getting Started
      12      ===============
      13        Once the library is imported you can load the font you want to use with
      14        L{tdl.set_font}.
      15        This is optional and when skipped will use a decent default font.
      16
      17        After that you call L{tdl.init} to set the size of the window and get the
      18        root console in return.
      19        This console is the canvas to what will appear on the screen.
      20
      21      Indexing Consoles
      22      =================
      23        For most methods taking a position you can use Python-style negative
      24        indexes to refer to the opposite side of a console with (-1, -1)
      25        starting at the bottom right.
      26        You can also check if a point is part of a console using containment
      27        logic i.e. ((x, y) in console).
      28
      29        You may also iterate over a console using a for statement.  This returns
      30        every x,y coordinate available to draw on but it will be extremely slow
      31        to actually operate on every coordinate individualy.
      32        Try to minimize draws by using an offscreen L{Console}, only drawing
      33        what needs to be updated, and using L{Console.blit}.
      34
      35      Drawing and Colors
      36      ==================
      37
      38        Once you have the root console from L{tdl.init} you can start drawing on
      39        it using a method such as L{Console.draw_char}.
      40        When using this method you can have the char parameter be an integer or a
      41        single character string.
      42
      43        The fg and bg parameters expect a variety of types.
      44        The parameters default to Ellipsis which will tell the function to
      45        use the colors previously set by the L{Console.set_colors} method.
      46        The colors set by L{Console.set_colors} are per each L{Console}/L{Window}
      47        and default to white on black.
      48        You can use a 3-item list/tuple of [red, green, blue] with integers in
      49        the 0-255 range with [0, 0, 0] being black and [255, 255, 255] being
      50        white.
      51        You can even use a single integer of 0xRRGGBB if you like.
      52
      53        Using None in the place of any of the three parameters (char, fg, bg)
      54        will tell the function to not overwrite that color or character.
      55
      56        After the drawing functions are called a call to L{tdl.flush} will update
      57        the screen.
      58
      59      @undocumented: style
      60  """
      61
      62  from __future__ import (absolute_import, division,
      63                          print_function, unicode_literals)
      64
      65  import sys as _sys
      66  import os as _os
      67
      68  import array as _array
      69  import weakref as _weakref
      70  import itertools as _itertools
      71  import textwrap as _textwrap
      72  import struct as _struct
      73  import re as _re
      74  import warnings as _warnings
      75
      76  from tcod import ffi as _ffi
      77  from tcod import lib as _lib
      78
      79  from . import event, map, noise
      80  from . import style as _style
      81
      82
      83  _IS_PYTHON3 = (_sys.version_info[0] == 3)
      84
      85  if _IS_PYTHON3: # some type lists to use with isinstance
      86      _INTTYPES = (int,)
      87      _NUMTYPES = (int, float)
      88      _STRTYPES = (str, bytes)
      89  else:
      90      _INTTYPES = (int, long)
      91      _NUMTYPES = (int, long, float)
      92      _STRTYPES = (str, unicode)
      93
      94 -def _encodeString(string): # still used for filepaths, and that's about it
      95      "changes string into bytes if running in python 3, for sending to ctypes"
      96      if isinstance(string, _STRTYPES):
      97          return string.encode()
      98      return string
      99
     100 -def _format_char(char):
     101      """Prepares a single character for passing to ctypes calls, needs to return
     102      an integer but can also pass None which will keep the current character
     103      instead of overwriting it.
     104
     105      This is called often and needs to be optimized whenever possible.
     106      """
     107      if char is None:
     108          return -1
     109      if isinstance(char, _STRTYPES) and len(char) == 1:
     110          return ord(char)
     111      try:
     112          return int(char) # allow all int-like objects
     113      except:
     114          raise TypeError('char single character string, integer, or None\nReceived: ' + repr(char))
     115
     116  _utf32_codec = {'little': 'utf-32le', 'big': 'utf-32le'}[_sys.byteorder]
     117
     118 -def _format_str(string):
     119      """Attempt fast string handing by decoding directly into an array."""
     120      if isinstance(string, _STRTYPES):
     121          if _IS_PYTHON3:
     122              array = _array.array('I')
     123              array.frombytes(string.encode(_utf32_codec))
     124          else: # Python 2
     125              if isinstance(string, unicode):
     126                  array = _array.array(b'I')
     127                  array.fromstring(string.encode(_utf32_codec))
     128              else:
     129                  array = _array.array(b'B')
     130                  array.fromstring(string)
     131          return array
     132      return string
     133
     134  _fontinitialized = False
     135  _rootinitialized = False
     136  _rootConsoleRef = None
     137
     138  _put_char_ex = _lib.TDL_console_put_char_ex
     139
     140  # python 2 to 3 workaround
     141  if _sys.version_info[0] == 2:
     142      int_types = (int, long)
     143  else:
     144      int_types = int
     145
     146
     147 -def _format_color(color, default=Ellipsis):
     148          if color is Ellipsis:
     149              return default
     150          if color is None:
     151              return -1
     152          if isinstance(color, (tuple, list)) and len(color) == 3:
     153              return (color[0] << 16) + (color[1] << 8) + color[2]
     154          try:
     155              return int(color) # allow all int-like objects
     156          except:
     157              raise TypeError('fg and bg must be a 3 item tuple, integer, Ellipsis, or None\nReceived: ' + repr(color))
     158
     159 -def _to_tcod_color(color):
     160      return _ffi.new('TCOD_color_t *', (color >> 16 & 0xff,
     161                                         color >> 8 & 0xff,
     162                                         color & 0xff))
     163
     164 -def _getImageSize(filename):
     165      """Try to get the width and height of a bmp of png image file"""
     166      result = None
     167      file = open(filename, 'rb')
     168      if file.read(8) == b'\x89PNG\r\n\x1a\n': # PNG
     169          while 1:
     170              length, = _struct.unpack('>i', file.read(4))
     171              chunkID = file.read(4)
     172              if chunkID == '': # EOF
     173                  break
     174              if chunkID == b'IHDR':
     175                  # return width, height
     176                  result = _struct.unpack('>ii', file.read(8))
     177                  break
     178              file.seek(4 + length, 1)
     179          file.close()
     180          return result
     181      file.seek(0)
     182      if file.read(8) == b'BM': # Bitmap
     183          file.seek(18, 0) # skip to size data
     184          result = _struct.unpack('<ii', file.read(8))
     185      file.close()
     186      return result # (width, height), or None
     187
     188 -class TDLError(Exception):
     189      """
     190      The catch all for most TDL specific errors.
     191      """
     192
     193 -class _BaseConsole(object):
     194      """
     195      Contains methods shared by both the L{Console} and L{Window} classes.
     196
     197      @undocumented: drawStr drawChar drawFrame drawRect
     198                     getCursor getSize getChar printStr setColors setMode
     199      @group Drawing Methods: draw_*, blit, clear
     200      @group Printing Methods: print_*, move, set_colors, set_mode, write, get_cursor
     201
     202      @undocumented: console
     203      @ivar width: The width of this console in tiles.  Do not overwrite this.
     204      @ivar height: The height of this console in tiles.  Do not overwrite this.
     205      """
     206      __slots__ = ('width', 'height', 'console', '_cursor', '_fg',
     207                   '_bg', '_blend', '__weakref__', '__dict__')
     208
     209 -    def __init__(self):
     210          self._cursor = (0, 0)
     211          self._scrollMode = 'error'
     212          self._fg = _format_color((255, 255, 255))
     213          self._bg = _format_color((0, 0, 0))
     214          self._blend = _lib.TCOD_BKGND_SET
     215
     216 -    def _normalizePoint(self, x, y):
     217          """Check if a point is in bounds and make minor adjustments.
     218
     219          Respects Pythons negative indexes.  -1 starts at the bottom right.
     220          Replaces the _drawable function
     221          """
     222          # cast to int, always faster than type checking
     223          x = int(x)
     224          y = int(y)
     225
     226          assert (-self.width <= x < self.width) and \
     227                 (-self.height <= y < self.height), \
     228                 ('(%i, %i) is an invalid postition on %s' % (x, y, self))
     229
     230          # handle negative indexes
     231          return (x % self.width, y % self.height)
     232
     233 -    def _normalizeRect(self, x, y, width, height):
     234          """Check if the rectangle is in bounds and make minor adjustments.
     235          raise AssertionError's for any problems
     236          """
     237          x, y = self._normalizePoint(x, y) # inherit _normalizePoint logic
     238
     239          assert width is None or isinstance(width, _INTTYPES), 'width must be an integer or None, got %s' % repr(width)
     240          assert height is None or isinstance(height, _INTTYPES), 'height must be an integer or None, got %s' % repr(height)
     241
     242          # if width or height are None then extend them to the edge
     243          if width is None:
     244              width = self.width - x
     245          elif width < 0: # handle negative numbers
     246              width += self.width
     247              width = max(0, width) # a 'too big' negative is clamped zero
     248          if height is None:
     249              height = self.height - y
     250              height = max(0, height)
     251          elif height < 0:
     252              height += self.height
     253
     254          # reduce rect size to bounds
     255          width = min(width, self.width - x)
     256          height = min(height, self.height - y)
     257
     258          return x, y, width, height
     259
     260 -    def _normalizeCursor(self, x, y):
     261          """return the normalized the cursor position."""
     262          width, height = self.get_size()
     263          assert width != 0 and height != 0, 'can not print on a console with a width or height of zero'
     264          while x >= width:
     265              x -= width
     266              y += 1
     267          while y >= height:
     268              if self._scrollMode == 'scroll':
     269                  y -= 1
     270                  self.scroll(0, -1)
     271              elif self._scrollMode == 'error':
     272                  # reset the cursor on error
     273                  self._cursor = (0, 0)
     274                  raise TDLError('Cursor has reached the end of the console')
     275          return (x, y)
     276
     277 -    def set_mode(self, mode):
     278          """Configure how this console will react to the cursor writing past the
     279          end if the console.
     280
     281          This is for methods that use the virtual cursor, such as L{print_str}.
     282
     283          @type mode: string
     284          @param mode: Possible settings are:
     285
     286                        - 'error' - A TDLError will be raised once the cursor
     287                          reaches the end of the console.  Everything up until
     288                          the error will still be drawn.
     289
     290                          This is the default setting.
     291
     292                        - 'scroll' - The console will scroll up as stuff is
     293                          written to the end.
     294
     295                          You can restrict the region with L{tdl.Window} when
     296                          doing this.
     297          @see: L{write}, L{print_str}
     298          """
     299          MODES = ['error', 'scroll']
     300          if mode.lower() not in MODES:
     301              raise TDLError('mode must be one of %s, got %s' % (MODES, repr(mode)))
     302          self._scrollMode = mode.lower()
     303
     304 -    def set_colors(self, fg=None, bg=None):
     305          """Sets the colors to be used with the L{print_str} and draw_* methods.
     306
     307          Values of None will only leave the current values unchanged.
     308
     309          @type fg: (r, g, b), int, Ellipsis, or None
     310          @type bg: (r, g, b), int, Ellipsis, or None
     311          @param fg: See Drawing and Colors at the L{module level docs<tdl>}
     312          @param bg: See Drawing and Colors at the L{module level docs<tdl>}
     313          @see: L{move}, L{print_str}
     314          """
     315          if fg is not None:
     316              self._fg = _format_color(fg, self._fg)
     317          if bg is not None:
     318              self._bg = _format_color(bg, self._bg)
     319
     320 -    def print_str(self, string):
     321          """Print a string at the virtual cursor.
     322
     323          Handles special characters such as '\\n' and '\\r'.
     324          Printing past the bottom of the console will scroll everything upwards
     325          if L{set_mode} is set to 'scroll'.
     326
     327          Colors can be set with L{set_colors} and the virtual cursor can be moved
     328          with L{move}.
     329
     330          @type string: string
     331          @param string:
     332          @see: L{draw_str}, L{move}, L{set_colors}, L{set_mode}, L{write},
     333                L{Window}
     334          """
     335          x, y = self._cursor
     336          for char in string:
     337              if char == '\n': # line break
     338                  x = 0
     339                  y += 1
     340                  continue
     341              if char == '\r': # return
     342                  x = 0
     343                  continue
     344              x, y = self._normalizeCursor(x, y)
     345              self.draw_char(x, y, char, self._fg, self._bg)
     346              x += 1
     347          self._cursor = (x, y)
     348
     349 -    def write(self, string):
     350          """This method mimics basic file-like behaviour.
     351
     352          Because of this method you can replace sys.stdout or sys.stderr with
     353          a L{Console} or L{Window} instance.
     354
     355          This is a convoluted process and behaviour seen now can be excepted to
     356          change on later versions.
     357
     358          @type string: string
     359          @see: L{set_colors}, L{set_mode}, L{Window}
     360          """
     361          # some 'basic' line buffer stuff.
     362          # there must be an easier way to do this.  The textwrap module didn't
     363          # help much.
     364          x, y = self._normalizeCursor(*self._cursor)
     365          width, height = self.get_size()
     366          wrapper = _textwrap.TextWrapper(initial_indent=(' '*x), width=width)
     367          writeLines = []
     368          for line in string.split('\n'):
     369              if line:
     370                  writeLines += wrapper.wrap(line)
     371                  wrapper.initial_indent = ''
     372              else:
     373                  writeLines.append([])
     374
     375          for line in writeLines:
     376              x, y = self._normalizeCursor(x, y)
     377              self.draw_str(x, y, line[x:], self._fg, self._bg)
     378              y += 1
     379              x = 0
     380          y -= 1
     381          self._cursor = (x, y)
     382
     383 -    def draw_char(self, x, y, char, fg=Ellipsis, bg=Ellipsis):
     384          """Draws a single character.
     385
     386          @type x: int
     387          @param x: X coordinate to draw at.
     388          @type y: int
     389          @param y: Y coordinate to draw at.
     390
     391          @type char: int, string, or None
     392          @param char: Should be an integer, single character string, or None.
     393
     394                       You can set the char parameter as None if you only want to change
     395                       the colors of the tile.
     396
     397          @type fg: (r, g, b), int, Ellipsis, or None
     398          @type bg: (r, g, b), int, Ellipsis, or None
     399          @param fg: See Drawing and Colors at the L{module level docs<tdl>}
     400          @param bg: See Drawing and Colors at the L{module level docs<tdl>}
     401
     402          @raise AssertionError: Having x or y values that can't be placed inside
     403                                 of the console will raise an AssertionError.
     404                                 You can use always use ((x, y) in console) to
     405                                 check if a tile is drawable.
     406          @see: L{get_char}
     407          """
     408          #x, y = self._normalizePoint(x, y)
     409          _put_char_ex(self.tcod_console, x, y, _format_char(char),
     410                       _format_color(fg, self._fg), _format_color(bg, self._bg), 1)
     411
     412 -    def draw_str(self, x, y, string, fg=Ellipsis, bg=Ellipsis):
     413          """Draws a string starting at x and y.
     414
     415          A string that goes past the right side will wrap around.  A string
     416          wrapping to below the console will raise a L{TDLError} but will still be
     417          written out.  This means you can safely ignore the errors with a
     418          try... except block if you're fine with partially written strings.
     419
     420          \\r and \\n are drawn on the console as normal character tiles.  No
     421          special encoding is done and any string will translate to the character
     422          table as is.
     423
     424          For a string drawing operation that respects special characters see
     425          L{print_str}.
     426
     427          @type x: int
     428          @param x: X coordinate to draw at.
     429          @type y: int
     430          @param y: Y coordinate to draw at.
     431
     432          @type string: string or iterable
     433          @param string: Can be a string or an iterable of numbers.
     434
     435                         Special characters are ignored and rendered as any other
     436                         character.
     437
     438          @type fg: (r, g, b), int, Ellipsis, or None
     439          @type bg: (r, g, b), int, Ellipsis, or None
     440          @param fg: See Drawing and Colors at the L{module level docs<tdl>}
     441          @param bg: See Drawing and Colors at the L{module level docs<tdl>}
     442
     443          @raise AssertionError: Having x or y values that can't be placed inside
     444                                 of the console will raise an AssertionError.
     445
     446                                 You can use always use ((x, y) in console) to
     447                                 check if a tile is drawable.
     448          @see: L{print_str}
     449          """
     450
     451          x, y = self._normalizePoint(x, y)
     452          fg, bg = _format_color(fg, self._fg), _format_color(bg, self._bg)
     453          width, height = self.get_size()
     454          batch = [] # prepare a batch operation
     455          def _drawStrGen(x=x, y=y, string=string, width=width, height=height):
     456              """Generator for draw_str
     457
     458              Iterates over ((x, y), ch) data for _set_batch, raising an
     459              error if the end of the console is reached.
     460              """
     461              for char in _format_str(string):
     462                  if y == height:
     463                      raise TDLError('End of console reached.')
     464                  #batch.append(((x, y), _format_char(char))) # ((x, y), ch)
     465                  yield((x, y), char)
     466                  x += 1 # advance cursor
     467                  if x == width: # line break
     468                      x = 0
     469                      y += 1
     470          self._set_batch(_drawStrGen(), fg, bg)
     471
     472 -    def draw_rect(self, x, y, width, height, string, fg=Ellipsis, bg=Ellipsis):
     473          """Draws a rectangle starting from x and y and extending to width and height.
     474
     475          If width or height are None then it will extend to the edge of the console.
     476
     477          @type x: int
     478          @param x: x coordinate to draw at.
     479          @type y: int
     480          @param y: y coordinate to draw at.
     481
     482          @type width: int or None
     483          @param width: Width of the rectangle.
     484
     485                        Can be None to extend to the bottom right of the
     486                        console or can be a negative number to be sized reltive
     487                        to the total size of the console.
     488          @type height: int or None
     489          @param height: Height of the rectangle.  See width.
     490
     491          @type string: int, string, or None
     492          @param string: Should be an integer, single character string, or None.
     493
     494                         You can set the char parameter as None if you only want
     495                         to change the colors of an area.
     496
     497          @type fg: (r, g, b), int, Ellipsis, or None
     498          @type bg: (r, g, b), int, Ellipsis, or None
     499          @param fg: See Drawing and Colors at the L{module level docs<tdl>}
     500          @param bg: See Drawing and Colors at the L{module level docs<tdl>}
     501
     502          @raise AssertionError: Having x or y values that can't be placed inside
     503                                 of the console will raise an AssertionError.
     504
     505                                 You can use always use ((x, y) in console) to
     506                                 check if a tile is drawable.
     507          @see: L{clear}, L{draw_frame}
     508          """
     509          x, y, width, height = self._normalizeRect(x, y, width, height)
     510          fg, bg = _format_color(fg, self._fg), _format_color(bg, self._bg)
     511          char = _format_char(string)
     512          # use itertools to make an x,y grid
     513          # using ctypes here reduces type converstions later
     514          #grid = _itertools.product((_ctypes.c_int(x) for x in range(x, x + width)),
     515          #                          (_ctypes.c_int(y) for y in range(y, y + height)))
     516          grid = _itertools.product((x for x in range(x, x + width)),
     517                                    (y for y in range(y, y + height)))
     518          # zip the single character in a batch variable
     519          batch = zip(grid, _itertools.repeat(char, width * height))
     520          self._set_batch(batch, fg, bg, nullChar=(char is None))
     521
     522 -    def draw_frame(self, x, y, width, height, string, fg=Ellipsis, bg=Ellipsis):
     523          """Similar to L{draw_rect} but only draws the outline of the rectangle.
     524
     525          @type x: int
     526          @param x: x coordinate to draw at.
     527          @type y: int
     528          @param y: y coordinate to draw at.
     529
     530          @type width: int or None
     531          @param width: Width of the rectangle.
     532
     533                        Can be None to extend to the bottom right of the
     534                        console or can be a negative number to be sized reltive
     535                        to the total size of the console.
     536          @type height: int or None
     537          @param height: Height of the rectangle.  See width.
     538
     539          @type string: int, string, or None
     540          @param string: Should be an integer, single character string, or None.
     541
     542                         You can set the char parameter as None if you only want
     543                         to change the colors of an area.
     544
     545          @type fg: (r, g, b), int, Ellipsis, or None
     546          @type bg: (r, g, b), int, Ellipsis, or None
     547          @param fg: See Drawing and Colors at the L{module level docs<tdl>}
     548          @param bg: See Drawing and Colors at the L{module level docs<tdl>}
     549
     550          @raise AssertionError: Having x or y values that can't be placed inside
     551                                 of the console will raise an AssertionError.
     552
     553                                 You can use always use ((x, y) in console) to
     554                                 check if a tile is drawable.
     555          @see: L{draw_rect}, L{Window}
     556          """
     557          x, y, width, height = self._normalizeRect(x, y, width, height)
     558          fg, bg = _format_color(fg, self._fg), _format_color(bg, self._bg)
     559          char = _format_char(string)
     560          if width == 1 or height == 1: # it's just a single width line here
     561              return self.draw_rect(x, y, width, height, char, fg, bg)
     562
     563          # draw sides of frame with draw_rect
     564          self.draw_rect(x, y, 1, height, char, fg, bg)
     565          self.draw_rect(x, y, width, 1, char, fg, bg)
     566          self.draw_rect(x + width - 1, y, 1, height, char, fg, bg)
     567          self.draw_rect(x, y + height - 1, width, 1, char, fg, bg)
     568
     569 -    def blit(self, source, x=0, y=0, width=None, height=None, srcX=0, srcY=0):
     570          """Blit another console or Window onto the current console.
     571
     572          By default it blits the entire source to the topleft corner.
     573
     574          @type source: L{Console} or L{Window}
     575          @param source: Source window can be a L{Console} or L{Window} instance.
     576                         It can even blit to itself without any problems.
     577
     578          @type x: int
     579          @param x: X coordinate to blit to.
     580          @type y: int
     581          @param y: Y coordinate to blit to.
     582
     583          @type width: int or None
     584          @param width: Width of the rectangle.
     585
     586                        Can be None to extend as far as possible to the
     587                        bottom right corner of the blit area or can be a negative
     588                        number to be sized reltive to the total size of the
     589                        B{destination} console.
     590          @type height: int or None
     591          @param height: Height of the rectangle.  See width.
     592
     593          @type srcX: int
     594          @param srcX: The source consoles x coordinate to blit from.
     595          @type srcY: int
     596          @param srcY: The source consoles y coordinate to blit from.
     597          """
     598          # hardcode alpha settings for now
     599          fgalpha=1.0
     600          bgalpha=1.0
     601
     602          assert isinstance(source, (Console, Window)), "source muse be a Window or Console instance"
     603
     604          # handle negative indexes and rects
     605          # negative width and height will be set realtive to the destination
     606          # and will also be clamped to the smallest Console
     607          x, y, width, height = self._normalizeRect(x, y, width, height)
     608          srcX, srcY, width, height = source._normalizeRect(srcX, srcY, width, height)
     609
     610          # translate source and self if any of them are Window instances
     611          srcX, srcY = source._translate(srcX, srcY)
     612          source = source.console
     613          x, y = self._translate(x, y)
     614          self = self.console
     615
     616          if self == source:
     617              # if we are the same console then we need a third console to hold
     618              # onto the data, otherwise it tries to copy into itself and
     619              # starts destroying everything
     620              tmp = Console(width, height)
     621              _lib.TCOD_console_blit(source.tcod_console,
     622                                     srcX, srcY, width, height,
     623                                     tmp.tcod_console, 0, 0, fgalpha, bgalpha)
     624              _lib.TCOD_console_blit(tmp.tcod_console, 0, 0, width, height,
     625                                     self.tcod_console, x, y, fgalpha, bgalpha)
     626          else:
     627              _lib.TCOD_console_blit(source.tcod_console,
     628                                     srcX, srcY, width, height,
     629                                     self.tcod_console, x, y, fgalpha, bgalpha)
     630
     631 -    def get_cursor(self):
     632          """Return the virtual cursor position.
     633
     634          @rtype: (x, y)
     635          @return: Returns (x, y), a 2-integer tuple containing where the next
     636                   L{print_str} call will start at.
     637
     638                   This can be changed with the L{move} method.
     639          @see: L{move}
     640          """
     641          x, y = self._cursor
     642          width, height = self.parent.get_size()
     643          while x >= width:
     644              x -= width
     645              y += 1
     646          if y >= height and self.scrollMode == 'scroll':
     647              y = height - 1
     648          return x, y
     649
     650 -    def get_size(self):
     651          """Return the size of the console as (width, height)
     652
     653          @rtype: (width, height)
     654          """
     655          return self.width, self.height
     656
     657 -    def __iter__(self):
     658          """Return an iterator with every possible (x, y) value for this console.
     659
     660          It goes without saying that working on the console this way is a
     661          slow process, especially for Python, and should be minimized.
     662          @rtype: iter((x, y), ...)
     663          """
     664          return _itertools.product(range(self.width), range(self.height))
     665
     666 -    def move(self, x, y):
     667          """Move the virtual cursor.
     668
     669          @type x: int
     670          @param x: X position to place the cursor.
     671          @type y: int
     672          @param y: Y position to place the cursor.
     673          @see: L{get_cursor}, L{print_str}, L{write}
     674          """
     675          self._cursor = self._normalizePoint(x, y)
     676
     677 -    def scroll(self, x, y):
     678          """Scroll the contents of the console in the direction of x,y.
     679
     680          Uncovered areas will be cleared to the default background color.
     681          Does not move the virutal cursor.
     682          @type x: int
     683          @param x: Distance to scroll along x-axis
     684          @type y: int
     685          @param y: Distance to scroll along y-axis
     686          @rtype: iter((x, y), ...)
     687          @return: Iterates over the (x, y) of any tile uncovered after scrolling.
     688          @see: L{set_colors}
     689          """
     690          assert isinstance(x, _INTTYPES), "x must be an integer, got %s" % repr(x)
     691          assert isinstance(y, _INTTYPES), "y must be an integer, got %s" % repr(x)
     692          def getSlide(x, length):
     693              """get the parameters needed to scroll the console in the given
     694              direction with x
     695              returns (x, length, srcx)
     696              """
     697              if x > 0:
     698                  srcx = 0
     699                  length -= x
     700              elif x < 0:
     701                  srcx = abs(x)
     702                  x = 0
     703                  length -= srcx
     704              else:
     705                  srcx = 0
     706              return x, length, srcx
     707          def getCover(x, length):
     708              """return the (x, width) ranges of what is covered and uncovered"""
     709              cover = (0, length) # everything covered
     710              uncover = None  # nothing uncovered
     711              if x > 0: # left side uncovered
     712                  cover = (x, length - x)
     713                  uncover = (0, x)
     714              elif x < 0: # right side uncovered
     715                  x = abs(x)
     716                  cover = (0, length - x)
     717                  uncover = (length - x, x)
     718              return cover, uncover
     719
     720          width, height = self.get_size()
     721          if abs(x) >= width or abs(y) >= height:
     722              return self.clear() # just clear the console normally
     723
     724          # get the ranges of the areas that will be uncovered
     725          coverX, uncoverX = getCover(x, width)
     726          coverY, uncoverY = getCover(y, height)
     727          # so at this point we know that coverX and coverY makes a rect that
     728          # encases the area that we end up blitting to.  uncoverX/Y makes a
     729          # rect in the corner of the uncovered area.  So we need to combine
     730          # the uncoverX/Y with coverY/X to make what's left of the uncovered
     731          # area.  Explaining it makes it mush easier to do now.
     732
     733          # But first we need to blit.
     734          x, width, srcx = getSlide(x, width)
     735          y, height, srcy = getSlide(y, height)
     736          self.blit(self, x, y, width, height, srcx, srcy)
     737          if uncoverX: # clear sides (0x20 is space)
     738              self.draw_rect(uncoverX[0], coverY[0], uncoverX[1], coverY[1],
     739                             0x20, self._fg, self._bg)
     740          if uncoverY: # clear top/bottom
     741              self.draw_rect(coverX[0], uncoverY[0], coverX[1], uncoverY[1],
     742                             0x20, self._fg, self._bg)
     743          if uncoverX and uncoverY: # clear corner
     744              self.draw_rect(uncoverX[0], uncoverY[0], uncoverX[1], uncoverY[1],
     745                             0x20, self._fg, self._bg)
     746
     747 -    def clear(self, fg=Ellipsis, bg=Ellipsis):
     748          """Clears the entire L{Console}/L{Window}.
     749
     750          Unlike other drawing functions, fg and bg can not be None.
     751
     752          @type fg: (r, g, b), int, or Ellipsis
     753          @type bg: (r, g, b), int, or Ellipsis
     754          @param fg: Can not be None.
     755                     See Drawing and Colors at the L{module level docs<tdl>}
     756          @param bg: See fg
     757
     758
     759          @type fg: (r, g, b)
     760          @param fg: Foreground color.
     761
     762                     Must be a 3-item list with integers that range 0-255.
     763
     764                     Unlike most other operations you cannot use None here.
     765                     To clear only the foreground or background use L{draw_rect}.
     766          @type bg: (r, g, b)
     767          @param bg: Background color.  See fg.
     768          @see: L{draw_rect}
     769          """
     770          raise NotImplementedError('this method is overwritten by subclasses')
     771
     772 -    def get_char(self, x, y):
     773          """Return the character and colors of a tile as (ch, fg, bg)
     774
     775          This method runs very slowly as is not recommended to be called
     776          frequently.
     777
     778          @rtype: (int, (r, g, b), (r, g, b))
     779          @returns: Returns a 3-item tuple.  The first item is an integer of the
     780                    character at the position (x, y) the second and third are the
     781                    foreground and background colors respectfully.
     782          @see: L{draw_char}
     783          """
     784          raise NotImplementedError('Method here only exists for the docstring')
     785
     786 -    def __contains__(self, position):
     787          """Use ((x, y) in console) to check if a position is drawable on this console.
     788          """
     789          x, y = position
     790          return (0 <= x < self.width) and (0 <= y < self.height)
     791
     792 -class Console(_BaseConsole):
     793      """Contains character and color data and can be drawn to.
     794
     795      The console created by the L{tdl.init} function is the root console and is the
     796      console that is rendered to the screen with L{flush}.
     797
     798      Any console created from the Console class is an off-screen console that
     799      can be drawn on before being L{blit} to the root console.
     800
     801      @undocumented: getChar
     802
     803      @ivar tcod_console: Public interface to the cffi TCOD_console_t object
     804                          of this instance.
     805
     806                          Feel free to pass this variable to libtcod-cffi calls
     807                          but keep in mind that as soon as Console instance is
     808                          garbage collected the tcod_console will be deleted.
     809      """
     810
     811      __slots__ = ('tcod_console',)
     812
     813 -    def __init__(self, width, height):
     814          """Create a new offscreen console.
     815
     816          @type width: int
     817          @param width: Width of the console in tiles
     818          @type height: int
     819          @param height: Height of the console in tiles
     820          """
     821          _BaseConsole.__init__(self)
     822          if not _rootinitialized:
     823              raise TDLError('Can not create Console instances before a call to tdl.init')
     824          self.tcod_console = _lib.TCOD_console_new(width, height)
     825          self.console = self
     826          self.width = width
     827          self.height = height
     828
     829      @classmethod
     830 -    def _newConsole(cls, console):
     831          """Make a Console instance, from a console ctype"""
     832          self = cls.__new__(cls)
     833          _BaseConsole.__init__(self)
     834          self.tcod_console = console
     835          self.console = self
     836          self.width = _lib.TCOD_console_get_width(console)
     837          self.height = _lib.TCOD_console_get_height(console)
     838          return self
     839
     840 -    def _root_unhook(self):
     841          """Change this root console into a normal Console object and
     842          delete the root console from TCOD
     843          """
     844          global _rootinitialized, _rootConsoleRef
     845          # do we recognise this as the root console?
     846          # if not then assume the console has already been taken care of
     847          if(_rootConsoleRef and _rootConsoleRef() is self):
     848              # turn this console into a regular console
     849              unhooked = _lib.TCOD_console_new(self.width, self.height)
     850              _lib.TCOD_console_blit(self.tcod_console,
     851                                     0, 0, self.width, self.height,
     852                                     unhooked, 0, 0, 1, 1)
     853              # delete root console from TDL and TCOD
     854              _rootinitialized = False
     855              _rootConsoleRef = None
     856              _lib.TCOD_console_delete(self.tcod_console)
     857              # this Console object is now a regular console
     858              self.tcod_console = unhooked
     859
     860 -    def __del__(self):
     861          """
     862          If the main console is garbage collected then the window will be closed as well
     863          """
     864          if self.tcod_console is None:
     865              return # this console was already deleted
     866          if self.tcod_console is _ffi.NULL:
     867              # a pointer to the special root console
     868              self._root_unhook() # unhook the console and leave it to the GC
     869              return
     870          # this is a normal console pointer and can be safely deleted
     871          _lib.TCOD_console_delete(self.tcod_console)
     872          self.tcod_console = None
     873
     874 -    def __copy__(self):
     875          # make a new class and blit
     876          clone = self.__class__(self.width, self.height)
     877          clone.blit(self)
     878          return clone
     879
     880 -    def __getstate__(self):
     881          # save data from get_char
     882          data = [self.get_char(x, y) for x,y in
     883                  _itertools.product(range(self.width), range(self.height))]
     884          return self.width, self.height, data
     885
     886 -    def __setstate__(self, state):
     887          # make console from __init__ and unpack a get_char array
     888          width, height, data = state
     889          self.__init__(width, height)
     890          for (x, y), graphic in zip(_itertools.product(range(width),
     891                                                        range(height)), data):
     892              self.draw_char(x, y, *graphic)
     893
     894 -    def _translate(self, x, y):
     895          """Convertion x and y to their position on the root Console for this Window
     896
     897          Because this is a Console instead of a Window we return the paramaters
     898          untouched"""
     899          return x, y
     900
     901 -    def clear(self, fg=Ellipsis, bg=Ellipsis):
     902          # inherit docstring
     903          assert fg is not None and bg is not None, 'Can not use None with clear'
     904          fg = _format_color(fg, self._fg)
     905          bg = _format_color(bg, self._bg)
     906          _lib.TCOD_console_set_default_foreground(self.tcod_console,
     907                                                   _to_tcod_color(fg)[0])
     908          _lib.TCOD_console_set_default_background(self.tcod_console,
     909                                                   _to_tcod_color(bg)[0])
     910          _lib.TCOD_console_clear(self.tcod_console)
     911
     912
     913 -    def _set_char(self, x, y, char, fg=None, bg=None,
     914                    bgblend=_lib.TCOD_BKGND_SET):
     915          """
     916          Sets a character.
     917          This is called often and is designed to be as fast as possible.
     918
     919          Because of the need for speed this function will do NO TYPE CHECKING
     920          AT ALL, it's up to the drawing functions to use the functions:
     921          _format_char and _format_color before passing to this."""
     922          # values are already formatted, honestly this function is redundant
     923          return _put_char_ex(self.tcod_console, x, y, char, fg, bg, bgblend)
     924
     925 -    def _set_batch(self, batch, fg, bg, bgblend=1, nullChar=False):
     926          """
     927          Try to perform a batch operation otherwise fall back to _set_char.
     928          If fg and bg are defined then this is faster but not by very
     929          much.
     930
     931          if any character is None then nullChar is True
     932
     933          batch is a iterable of [(x, y), ch] items
     934          """
     935          for (x, y), char in batch:
     936              self._set_char(x, y, char, fg, bg, bgblend)
     937
     938 -    def get_char(self, x, y):
     939          # inherit docstring
     940          x, y = self._normalizePoint(x, y)
     941          char = _lib.TCOD_console_get_char(self.tcod_console, x, y)
     942          bg = _lib.TCOD_console_get_char_background(self.tcod_console, x, y)
     943          fg = _lib.TCOD_console_get_char_foreground(self.tcod_console, x, y)
     944          return char, (fg.r, fg.g, fg.b), (bg.r, bg.g, bg.b)
     945
     946 -    def __repr__(self):
     947          return "<Console (Width=%i Height=%i)>" % (self.width, self.height)
     948
     949
     950 -class Window(_BaseConsole):
     951      """A Window contains a small isolated part of a Console.
     952
     953      Drawing on the Window draws on the Console.
     954
     955      Making a Window and setting its width or height to None will extend it to
     956      the edge of the console.
     957
     958      @undocumented: getChar
     959      """
     960
     961      __slots__ = ('parent', 'x', 'y')
     962
     963 -    def __init__(self, console, x, y, width, height):
     964          """Isolate part of a L{Console} or L{Window} instance.
     965
     966          @type console: L{Console} or L{Window}
     967          @param console: The parent object which can be a L{Console} or another
     968                          L{Window} instance.
     969
     970          @type x: int
     971          @param x: X coordinate to place the Window.
     972
     973                    This follows the normal rules for indexing so you can use a
     974                    negative integer to place the Window relative to the bottom
     975                    right of the parent Console instance.
     976          @type y: int
     977          @param y: Y coordinate to place the Window.
     978
     979                    See x.
     980
     981          @type width: int or None
     982          @param width: Width of the Window.
     983
     984                        Can be None to extend as far as possible to the
     985                        bottom right corner of the parent Console or can be a
     986                        negative number to be sized reltive to the Consoles total
     987                        size.
     988          @type height: int or None
     989          @param height: Height of the Window.
     990
     991                         See width.
     992          """
     993          _BaseConsole.__init__(self)
     994          assert isinstance(console, (Console, Window)), 'console parameter must be a Console or Window instance, got %s' % repr(console)
     995          self.parent = console
     996          self.x, self.y, self.width, self.height = console._normalizeRect(x, y, width, height)
     997          if isinstance(console, Console):
     998              self.console = console
     999          else:
    1000              self.console = self.parent.console
    1001
    1002 -    def _translate(self, x, y):
    1003          """Convertion x and y to their position on the root Console"""
    1004          # we add our position relative to our parent and then call then next parent up
    1005          return self.parent._translate((x + self.x), (y + self.y))
    1006
    1007 -    def clear(self, fg=Ellipsis, bg=Ellipsis):
    1008          # inherit docstring
    1009          assert fg is not None and bg is not None, 'Can not use None with clear'
    1010          if fg is Ellipsis:
    1011              fg = self._fg
    1012          if bg is Ellipsis:
    1013              bg = self._bg
    1014          self.draw_rect(0, 0, None, None, 0x20, fg, bg)
    1015
    1016 -    def _set_char(self, x, y, char=None, fg=None, bg=None, bgblend=1):
    1017          self.parent._set_char((x + self.x), (y + self.y), char, fg, bg, bgblend)
    1018
    1019 -    def _set_batch(self, batch, *args, **kargs):
    1020          # positional values will need to be translated to the parent console
    1021          myX = self.x # remove dots for speed up
    1022          myY = self.y
    1023          self.parent._set_batch((((x + myX, y + myY), ch)
    1024                                     for ((x, y), ch) in batch), *args, **kargs)
    1025
    1026
    1027 -    def draw_char(self, x, y, char, fg=Ellipsis, bg=Ellipsis):
    1028          # inherit docstring
    1029          x, y = self._normalizePoint(x, y)
    1030          if fg is Ellipsis:
    1031              fg = self._fg
    1032          if bg is Ellipsis:
    1033              bg = self._bg
    1034          self.parent.draw_char(x + self.x, y + self.y, char, fg, bg)
    1035
    1036 -    def draw_rect(self, x, y, width, height, string, fg=Ellipsis, bg=Ellipsis):
    1037          # inherit docstring
    1038          x, y, width, height = self._normalizeRect(x, y, width, height)
    1039          if fg is Ellipsis:
    1040              fg = self._fg
    1041          if bg is Ellipsis:
    1042              bg = self._bg
    1043          self.parent.draw_rect(x + self.x, y + self.y, width, height,
    1044                                string, fg, bg)
    1045
    1046 -    def draw_frame(self, x, y, width, height, string, fg=Ellipsis, bg=Ellipsis):
    1047          # inherit docstring
    1048          x, y, width, height = self._normalizeRect(x, y, width, height)
    1049          if fg is Ellipsis:
    1050              fg = self._fg
    1051          if bg is Ellipsis:
    1052              bg = self._bg
    1053          self.parent.draw_frame(x + self.x, y + self.y, width, height,
    1054                                 string, fg, bg)
    1055
    1056 -    def get_char(self, x, y):
    1057          # inherit docstring
    1058          x, y = self._normalizePoint(x, y)
    1059          return self.console.get_char(self._translate(x, y))
    1060
    1061 -    def __repr__(self):
    1062          return "<Window(X=%i Y=%i Width=%i Height=%i)>" % (self.x, self.y,
    1063                                                            self.width,
    1064                                                            self.height)
    1065
    1066
    1067 -def init(width, height, title=None, fullscreen=False, renderer='OPENGL'):
    1068      """Start the main console with the given width and height and return the
    1069      root console.
    1070
    1071      Call the consoles drawing functions.  Then remember to use L{tdl.flush} to
    1072      make what's drawn visible on the console.
    1073
    1074      @type width: int
    1075      @param width: width of the root console (in tiles)
    1076
    1077      @type height: int
    1078      @param height: height of the root console (in tiles)
    1079
    1080      @type title: string
    1081      @param title: Text to display as the window title.
    1082
    1083                    If left None it defaults to the running scripts filename.
    1084
    1085      @type fullscreen: boolean
    1086      @param fullscreen: Can be set to True to start in fullscreen mode.
    1087
    1088      @type renderer: string
    1089      @param renderer: Can be one of 'GLSL', 'OPENGL', or 'SDL'.
    1090
    1091                       Due to way Python works you're unlikely to see much of an
    1092                       improvement by using 'GLSL' over 'OPENGL' as most of the
    1093                       time Python is slow interacting with the console and the
    1094                       rendering itself is pretty fast even on 'SDL'.
    1095
    1096      @rtype: L{Console}
    1097      @return: The root console.  Only what is drawn on the root console is
    1098               what's visible after a call to L{tdl.flush}.
    1099               After the root console is garbage collected, the window made by
    1100               this function will close.
    1101      @see: L{Console}, L{set_font}
    1102      """
    1103      RENDERERS = {'GLSL': 0, 'OPENGL': 1, 'SDL': 2}
    1104      global _rootinitialized, _rootConsoleRef
    1105      if not _fontinitialized: # set the default font to the one that comes with tdl
    1106          set_font(_os.path.join(__path__[0], 'terminal8x8.png'),
    1107                   None, None, True, True)
    1108
    1109      if renderer.upper() not in RENDERERS:
    1110          raise TDLError('No such render type "%s", expected one of "%s"' % (renderer, '", "'.join(RENDERERS)))
    1111      renderer = RENDERERS[renderer.upper()]
    1112
    1113      # If a console already exists then make a clone to replace it
    1114      if _rootConsoleRef and _rootConsoleRef():
    1115          # unhook the root console, turning into a regular console and deleting
    1116          # the root console from libTCOD
    1117          _rootConsoleRef()._root_unhook()
    1118
    1119      if title is None: # use a default title
    1120          if _sys.argv:
    1121              # Use the script filename as the title.
    1122              title = _os.path.basename(_sys.argv[0])
    1123          else:
    1124              title = 'python-tdl'
    1125
    1126      _lib.TCOD_console_init_root(width, height, _encodeString(title), fullscreen, renderer)
    1127
    1128      #event.get() # flush the libtcod event queue to fix some issues
    1129      # issues may be fixed already
    1130
    1131      event._eventsflushed = False
    1132      _rootinitialized = True
    1133      rootconsole = Console._newConsole(_ffi.NULL)
    1134      _rootConsoleRef = _weakref.ref(rootconsole)
    1135
    1136      return rootconsole
    1137
    1138 -def flush():
    1139      """Make all changes visible and update the screen.
    1140
    1141      Remember to call this function after drawing operations.
    1142      Calls to flush will enfore the frame rate limit set by L{tdl.set_fps}.
    1143
    1144      This function can only be called after L{tdl.init}
    1145      """
    1146      if not _rootinitialized:
    1147          raise TDLError('Cannot flush without first initializing with tdl.init')
    1148      # flush the OS event queue, preventing lock-ups if not done manually
    1149      event.get()
    1150      _lib.TCOD_console_flush()
    1151
    1152 -def set_font(path, columns=None, rows=None, columnFirst=False,
    1153               greyscale=False, altLayout=False):
    1154      """Changes the font to be used for this session.
    1155      This should be called before L{tdl.init}
    1156
    1157      If the font specifies its size in its filename (i.e. font_NxN.png) then this
    1158      function can auto-detect the tileset formatting and the parameters columns
    1159      and rows can be left None.
    1160
    1161      While it's possible you can change the font mid program it can sometimes
    1162      break in rare circumstances.  So use caution when doing this.
    1163
    1164      @type path: string
    1165      @param path: Must be a string filepath where a bmp or png file is found.
    1166
    1167      @type columns: int
    1168      @param columns: Number of columns in the tileset.
    1169
    1170                      Can be left None for auto-detection.
    1171
    1172      @type rows: int
    1173      @param rows: Number of rows in the tileset.
    1174
    1175                   Can be left None for auto-detection.
    1176
    1177      @type columnFirst: boolean
    1178      @param columnFirst: Defines if the characer order goes along the rows or
    1179                          colomns.
    1180                          It should be True if the charater codes 0-15 are in the
    1181                          first column.
    1182                          And should be False if the characters 0-15
    1183                          are in the first row.
    1184
    1185      @type greyscale: boolean
    1186      @param greyscale: Creates an anti-aliased font from a greyscale bitmap.
    1187                        Otherwise it uses the alpha channel for anti-aliasing.
    1188
    1189                        Unless you actually need anti-aliasing from a font you
    1190                        know uses a smooth greyscale channel you should leave
    1191                        this on False.
    1192
    1193      @type altLayout: boolean
    1194      @param altLayout: An alternative layout with space in the upper left
    1195                        corner.
    1196                        The colomn parameter is ignored if this is True,
    1197                        find examples of this layout in the font/libtcod/
    1198                        directory included with the python-tdl source.
    1199
    1200      @raise TDLError: Will be raised if no file is found at path or if auto-
    1201                       detection fails.
    1202
    1203      @note: A png file that's been optimized can fail to load correctly on
    1204             MAC OS X creating a garbled mess when rendering.
    1205             Don't use a program like optipng or just use bmp files instead if
    1206             you want your program to work on macs.
    1207      """
    1208      # put up some constants that are only used here
    1209      FONT_LAYOUT_ASCII_INCOL = 1
    1210      FONT_LAYOUT_ASCII_INROW = 2
    1211      FONT_TYPE_GREYSCALE = 4
    1212      FONT_LAYOUT_TCOD = 8
    1213      global _fontinitialized
    1214      _fontinitialized = True
    1215      flags = 0
    1216      if altLayout:
    1217          flags |= FONT_LAYOUT_TCOD
    1218      elif columnFirst:
    1219          flags |= FONT_LAYOUT_ASCII_INCOL
    1220      else:
    1221          flags |= FONT_LAYOUT_ASCII_INROW
    1222      if greyscale:
    1223          flags |= FONT_TYPE_GREYSCALE
    1224      if not _os.path.exists(path):
    1225          raise TDLError('no file exists at: "%s"' % path)
    1226      path = _os.path.abspath(path)
    1227
    1228      # and the rest is the auto-detect script
    1229      imgSize = _getImageSize(path) # try to find image size
    1230      if imgSize:
    1231          imgWidth, imgHeight = imgSize
    1232          # try to get font size from filename
    1233          match = _re.match('.*?([0-9]+)[xX]([0-9]+)', _os.path.basename(path))
    1234          if match:
    1235              fontWidth, fontHeight = match.groups()
    1236              fontWidth, fontHeight = int(fontWidth), int(fontHeight)
    1237
    1238              # estimate correct tileset size
    1239              estColumns, remC = divmod(imgWidth, fontWidth)
    1240              estRows, remR = divmod(imgHeight, fontHeight)
    1241              if remC or remR:
    1242                  _warnings.warn("Font may be incorrectly formatted.")
    1243
    1244              if not columns:
    1245                  columns = estColumns
    1246              if not rows:
    1247                  rows = estRows
    1248          else:
    1249              # the font name excluded the fonts size
    1250              if not (columns and rows):
    1251                  # no matched font size and no tileset is given
    1252                  raise TDLError('%s has no font size in filename' % _os.path.basename(path))
    1253
    1254          if columns and rows:
    1255              # confirm user set options
    1256              if (fontWidth * columns != imgWidth or
    1257                  fontHeight * rows != imgHeight):
    1258                  _warnings.warn("set_font parameters are set as if the image size is (%d, %d) when the detected size is actually (%i, %i)"
    1259                               % (fontWidth * columns, fontHeight * rows,
    1260                                  imgWidth, imgHeight))
    1261      else:
    1262          _warnings.warn("%s is probably not an image." % _os.path.basename(path))
    1263
    1264      if not (columns and rows):
    1265          # didn't auto-detect
    1266          raise TDLError('Can not auto-detect the tileset of %s' % _os.path.basename(path))
    1267
    1268      _lib.TCOD_console_set_custom_font(_encodeString(path), flags, columns, rows)
    1269
    1270 -def get_fullscreen():
    1271      """Returns True if program is fullscreen.
    1272
    1273      @rtype: boolean
    1274      @return: Returns True if the window is in fullscreen mode.
    1275               Otherwise returns False.
    1276      """
    1277      if not _rootinitialized:
    1278          raise TDLError('Initialize first with tdl.init')
    1279      return _lib.TCOD_console_is_fullscreen()
    1280
    1281 -def set_fullscreen(fullscreen):
    1282      """Changes the fullscreen state.
    1283
    1284      @type fullscreen: boolean
    1285      """
    1286      if not _rootinitialized:
    1287          raise TDLError('Initialize first with tdl.init')
    1288      _lib.TCOD_console_set_fullscreen(fullscreen)
    1289
    1290 -def set_title(title):
    1291      """Change the window title.
    1292
    1293      @type title: string
    1294      """
    1295      if not _rootinitialized:
    1296          raise TDLError('Not initilized.  Set title with tdl.init')
    1297      _lib.TCOD_console_set_window_title(_encodeString(title))
    1298
    1299 -def screenshot(path=None):
    1300      """Capture the screen and save it as a png file
    1301
    1302      @type path: string
    1303      @param path: The filepath to save the screenshot.
    1304
    1305                   If path is None then the image will be placed in the current
    1306                   folder with the names:
    1307                   screenshot001.png, screenshot002.png, ...
    1308      """
    1309      if not _rootinitialized:
    1310          raise TDLError('Initialize first with tdl.init')
    1311      if isinstance(path, str):
    1312          _lib.TCOD_sys_save_screenshot(_encodeString(path))
    1313      elif path is None: # save to screenshot001.png, screenshot002.png, ...
    1314          filelist = _os.listdir('.')
    1315          n = 1
    1316          filename = 'screenshot%.3i.png' % n
    1317          while filename in filelist:
    1318              n += 1
    1319              filename = 'screenshot%.3i.png' % n
    1320          _lib.TCOD_sys_save_screenshot(_encodeString(filename))
    1321      else: # assume file like obj
    1322          #save to temp file and copy to file-like obj
    1323          tmpname = _os.tempnam()
    1324          _lib.TCOD_sys_save_screenshot(_encodeString(tmpname))
    1325          with tmpname as tmpfile:
    1326              path.write(tmpfile.read())
    1327          _os.remove(tmpname)
    1328      #else:
    1329      #    raise TypeError('path is an invalid type: %s' % type(path))
    1330
    1331 -def set_fps(frameRate):
    1332      """Set the maximum frame rate.
    1333
    1334      @type frameRate: int
    1335      @param frameRate: Further calls to L{tdl.flush} will limit the speed of
    1336                        the program to run at <frameRate> frames per second. Can
    1337                        also be set to 0 to run without a limit.
    1338
    1339                        Defaults to None.
    1340      """
    1341      if frameRate is None:
    1342          frameRate = 0
    1343      assert isinstance(frameRate, _INTTYPES), 'frameRate must be an integer or None, got: %s' % repr(frameRate)
    1344      _lib.TCOD_sys_set_fps(frameRate)
    1345
    1346 -def get_fps():
    1347      """Return the current frames per second of the running program set by
    1348      L{set_fps}
    1349
    1350      @rtype: int
    1351      @return: Returns the frameRate set by set_fps.
    1352               If set to no limit, this will return 0.
    1353      """
    1354      return _lib.TCOD_sys_get_fps()
    1355
    1356 -def force_resolution(width, height):
    1357      """Change the fullscreen resoulution
    1358
    1359      @type width: int
    1360      @type height: int
    1361      """
    1362      _lib.TCOD_sys_force_fullscreen_resolution(width, height)
    1363
    1364
    1365  __all__ = [_var for _var in locals().keys() if _var[0] != '_'] # remove modules from __all__
    1366  __all__ += ['_BaseConsole'] # keep this object public to show the documentation in epydoc
    1367  __all__.remove('absolute_import')
    1368  __all__.remove('division')
    1369  __all__.remove('print_function')
    1370  __all__.remove('unicode_literals')
    1371
    1372  # backported function names
    1373  _BaseConsole.setMode = _style.backport(_BaseConsole.set_mode)
    1374  _BaseConsole.setColors = _style.backport(_BaseConsole.set_colors)
    1375  _BaseConsole.printStr = _style.backport(_BaseConsole.print_str)
    1376  _BaseConsole.drawChar = _style.backport(_BaseConsole.draw_char)
    1377  _BaseConsole.drawStr = _style.backport(_BaseConsole.draw_str)
    1378  _BaseConsole.drawRect = _style.backport(_BaseConsole.draw_rect)
    1379  _BaseConsole.drawFrame = _style.backport(_BaseConsole.draw_frame)
    1380  _BaseConsole.getCursor = _style.backport(_BaseConsole.get_cursor)
    1381  _BaseConsole.getSize = _style.backport(_BaseConsole.get_size)
    1382  _BaseConsole.getChar = _style.backport(_BaseConsole.get_char)
    1383
    1384  Console.getChar = _style.backport(Console.get_char)
    1385
    1386  Window.drawChar = _style.backport(Window.draw_char)
    1387  Window.drawRect = _style.backport(Window.draw_rect)
    1388  Window.drawFrame = _style.backport(Window.draw_frame)
    1389  Window.getChar = _style.backport(Window.get_char)
    1390
    1391  setFont = _style.backport(set_font)
    1392  getFullscreen = _style.backport(get_fullscreen)
    1393  setFullscreen = _style.backport(set_fullscreen)
    1394  setTitle = _style.backport(set_title)
    1395  setFPS = _style.backport(set_fps)
    1396  getFPS = _style.backport(get_fps)
    1397  forceResolution = _style.backport(force_resolution)
    1398
    1399  __license__ = "Simplified BSD License"
    1400  __author__ = 'Kyle Stewart'
    1401  __contact__ = "4b796c65+pythonTDL@gmail.com"
    1402  __email__ = "4b796c65+pythonTDL@gmail.com"
    1403  __version__ = open(_os.path.join(__path__[0], 'version.txt'), 'r').read()
    1404