#
# libtcod Python wrapper
# Copyright (c) 2008-2018 Jice & Mingos & rmtew
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * The name of Jice or Mingos may not be used to endorse or promote
#       products derived from this software without specific prior written
#       permission.
#
# THIS SOFTWARE IS PROVIDED BY JICE, MINGOS AND RMTEW ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL JICE, MINGOS OR RMTEW BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
from __future__ import print_function

import atexit
import ctypes
import os
import struct
import sys
import warnings
from ctypes import *

warnings.warn(
    """
This implementation of libtcodpy is no longer maintained.
python-tcod should be used as a drop-in replacement.
https://github.com/libtcod/python-tcod

To switch from libtcodpy to python-tcod:
* Update your current code base to Python 3.
* If on Linux, run: "sudo apt install gcc python3-dev libsdl2-dev libffi-dev"
* Install python-tcod using pip: "python3 -m pip install tcod"
* Delete the "libtcodpy/" directory and all related ".dll"/".so" files.
* Make sure that the python installation you run is the one you've installed python-tcod on.

No additional changes are required, you can continue with a tutorial or with documentation designed for libtcodpy.

Binary distributions can be made using PyInstaller.""",
    FutureWarning,
    stacklevel=2,
)

# We do not have a fully unicode API on libtcod, so all unicode strings have to
# be implicitly converted to ascii, and any unicode specific operations have to
# be explicitly made by users
#   v = v.encode('latin-1')
# Returned byte strings from the api, should be converted to unicode, so that
# if formatted via %, do not appear as "b'sds'".
#   v = v.decode("utf-8")
is_python_3 = sys.version_info > (3, 0)

if is_python_3:

    def convert_to_ascii(v):
        if not isinstance(v, bytes):
            return v.encode("utf-8")
        warnings.warn("Passing bytes to this call is deprecated.", DeprecationWarning, stacklevel=3)
        return v


else:

    def convert_to_ascii(v):
        if isinstance(v, unicode):
            return v.encode("utf-8")
        return v


if sys.version_info[0] == 2:  # Python 2

    def _bytes(string):
        if isinstance(string, unicode):
            return string.encode("latin-1")
        return string

    def _unicode(string):
        if not isinstance(string, unicode):
            return string.decode("latin-1")
        return string


else:  # Python 3

    def _bytes(string):
        if isinstance(string, str):
            return string.encode("latin-1")
        warnings.warn("Passing bytes to this call is deprecated.", DeprecationWarning, stacklevel=4)
        return string

    def _unicode(string):
        if isinstance(string, bytes):
            warnings.warn("Passing bytes to this call is deprecated.", DeprecationWarning, stacklevel=4)
            return string.decode("latin-1")
        return string


def _fmt_bytes(string):
    return _bytes(string).replace(b"%", b"%%")


def _fmt_unicode(string):
    return _unicode(string).replace(u"%", u"%%")


if not hasattr(ctypes, "c_bool"):  # for Python < 2.6
    c_bool = c_uint8

c_void = None

try:  # import NumPy if available
    import numpy

    numpy_available = True
except ImportError:
    numpy_available = False

LINUX = False
MAC = False
MINGW = False
MSVC = False


def _get_cdll(libname):
    """
    get the library libname using a manual search path that will first
    check the package directory and then the development path

    returns the ctypes lib object
    """

    def get_pe_architecture(filePath):
        # From: https://github.com/tgandor/meats/blob/master/missing/arch_of.py
        with open(filePath, "rb") as f:
            doshdr = f.read(64)
            magic, padding, offset = struct.unpack("2s58si", doshdr)
            # print (magic, offset)
            if magic != b"MZ":
                return None
            f.seek(offset, os.SEEK_SET)
            pehdr = f.read(6)
            # careful! H == unsigned short, x64 is negative with signed
            magic, padding, machine = struct.unpack("2s2sH", pehdr)
            # print (magic, hex(machine))
            if magic != b"PE":
                return None
            if machine == 0x014C:
                return "i386"
            if machine == 0x0200:
                return "IA64"
            if machine == 0x8664:
                return "x64"
            return "unknown"

    pythonExePath = sys.executable
    pythonExeArchitecture = get_pe_architecture(pythonExePath)

    pathsToTry = []
    # 1. Try the directory this script is located in.
    pathsToTry.append(os.path.join(__path__[0], libname))
    # 2. Try the directory of the command-line script.
    scriptFilePath = sys.argv[0]
    scriptPath = os.path.dirname(scriptFilePath)
    if len(scriptPath):
        pathsToTry.append(os.path.join(scriptPath, libname))
    else:
        pathsToTry.append(os.path.join(os.getcwd(), libname))
    # 3. Try the environment variable LIBTCOD_DLL_PATH.
    if "LIBTCOD_DLL_PATH" in os.environ:
        envPaths = os.environ["LIBTCOD_DLL_PATH"].split(";")
        for envPath in envPaths:
            if os.path.exists(envPath):
                pathsToTry.append(os.path.join(envPath, libname))
    # 4. Try the top-level path in the development tree.
    potentialTopLevelPath = os.path.realpath(os.path.join(__path__[0], os.pardir, os.pardir))
    pythonPath = os.path.join(potentialTopLevelPath, "python")
    if os.path.exists(pythonPath):
        pathsToTry.append(os.path.join(potentialTopLevelPath, libname))

    for libPath in pathsToTry:
        if os.path.exists(libPath):
            # get library from the package
            libArchitecture = get_pe_architecture(libPath)
            if libArchitecture != pythonExeArchitecture:
                libName = os.path.basename(libPath)
                print(
                    "Error: Incompatible architecture, python is %s, %s is %s"
                    % (pythonExeArchitecture, libName, libArchitecture)
                )
                sys.exit(1)
            return ctypes.cdll[libPath]

    raise Exception("unable to locate: " + libname)


if sys.platform.find("linux") != -1:
    _lib = _get_cdll("libtcod.so")
    LINUX = True
elif sys.platform.find("darwin") != -1:
    _lib = _get_cdll("libtcod.dylib")
    MAC = True
elif sys.platform.find("haiku") != -1:
    _lib = _get_cdll("libtcod.so")
    HAIKU = True
else:
    _get_cdll("SDL2.dll")
    _lib = _get_cdll("libtcod.dll")
    MSVC = True
    # On Windows, ctypes doesn't work well with function returning structs,
    # so we have to user the _wrapper functions instead
    for function_name in [
        "TCOD_color_equals",
        "TCOD_color_add",
        "TCOD_color_subtract",
        "TCOD_color_multiply",
        "TCOD_color_multiply_scalar",
        "TCOD_color_lerp",
        "TCOD_color_get_HSV",
        "TCOD_color_get_hue",
        "TCOD_color_get_saturation",
        "TCOD_color_get_value",
        "TCOD_console_get_default_background",
        "TCOD_console_get_default_foreground",
        "TCOD_console_set_default_background",
        "TCOD_console_set_default_foreground",
        "TCOD_console_get_char_foreground",
        "TCOD_console_get_char_background",
        "TCOD_console_set_char_background",
        "TCOD_console_set_char_foreground",
        "TCOD_console_put_char_ex",
        "TCOD_console_set_fade",
        "TCOD_console_get_fading_color",
        "TCOD_console_set_color_control",
        "TCOD_image_clear",
        "TCOD_image_get_pixel",
        "TCOD_image_get_mipmap_pixel",
        "TCOD_image_put_pixel",
        "TCOD_image_set_key_color",
        "TCOD_parser_get_color_property",
        "TCOD_console_set_key_color",
    ]:
        wrapper_func = getattr(_lib, function_name + "_wrapper", None)
        if wrapper_func is not None:
            setattr(_lib, function_name, wrapper_func)
        else:
            raise Exception("unable to find wrapper", function_name)

HEXVERSION = 0x010604
STRVERSION = "1.6.4"
TECHVERSION = 0x01060400

############################
# color module
############################


class Color(Structure):
    _fields_ = [
        ("r", c_uint8),
        ("g", c_uint8),
        ("b", c_uint8),
    ]

    def __eq__(self, c):
        return _lib.TCOD_color_equals(self, c)

    def __mul__(self, c):
        if isinstance(c, Color):
            return _lib.TCOD_color_multiply(self, c)
        else:
            return _lib.TCOD_color_multiply_scalar(self, c_float(c))

    def __add__(self, c):
        return _lib.TCOD_color_add(self, c)

    def __sub__(self, c):
        return _lib.TCOD_color_subtract(self, c)

    def __repr__(self):
        return "Color(%d,%d,%d)" % (self.r, self.g, self.b)

    def __getitem__(self, i):
        if type(i) == str:
            return getattr(self, i)
        else:
            return getattr(self, "rgb"[i])

    def __setitem__(self, i, c):
        if type(i) == str:
            setattr(self, i, c)
        else:
            setattr(self, "rgb"[i], c)

    def __iter__(self):
        yield self.r
        yield self.g
        yield self.b


_lib.TCOD_color_equals.restype = c_bool
_lib.TCOD_color_equals.argtypes = [Color, Color]

_lib.TCOD_color_add.restype = Color
_lib.TCOD_color_add.argtypes = [Color, Color]

_lib.TCOD_color_subtract.restype = Color
_lib.TCOD_color_subtract.argtypes = [Color, Color]

_lib.TCOD_color_multiply.restype = Color
_lib.TCOD_color_multiply.argtypes = [Color, Color]

_lib.TCOD_color_multiply_scalar.restype = Color
_lib.TCOD_color_multiply_scalar.argtypes = [Color, c_float]

# Should be valid on any platform, check it!  Has to be done after Color is defined.
# NOTE(rmtew): This should ideally be deleted.  Most of it is moved or duplicated here.
if MAC:
    from .cprotos import setup_protos

    setup_protos(_lib)


# default colors
# grey levels
black = Color(0, 0, 0)
darkest_grey = Color(31, 31, 31)
darker_grey = Color(63, 63, 63)
dark_grey = Color(95, 95, 95)
grey = Color(127, 127, 127)
light_grey = Color(159, 159, 159)
lighter_grey = Color(191, 191, 191)
lightest_grey = Color(223, 223, 223)
darkest_gray = Color(31, 31, 31)
darker_gray = Color(63, 63, 63)
dark_gray = Color(95, 95, 95)
gray = Color(127, 127, 127)
light_gray = Color(159, 159, 159)
lighter_gray = Color(191, 191, 191)
lightest_gray = Color(223, 223, 223)
white = Color(255, 255, 255)

# sepia
darkest_sepia = Color(31, 24, 15)
darker_sepia = Color(63, 50, 31)
dark_sepia = Color(94, 75, 47)
sepia = Color(127, 101, 63)
light_sepia = Color(158, 134, 100)
lighter_sepia = Color(191, 171, 143)
lightest_sepia = Color(222, 211, 195)

# standard colors
red = Color(255, 0, 0)
flame = Color(255, 63, 0)
orange = Color(255, 127, 0)
amber = Color(255, 191, 0)
yellow = Color(255, 255, 0)
lime = Color(191, 255, 0)
chartreuse = Color(127, 255, 0)
green = Color(0, 255, 0)
sea = Color(0, 255, 127)
turquoise = Color(0, 255, 191)
cyan = Color(0, 255, 255)
sky = Color(0, 191, 255)
azure = Color(0, 127, 255)
blue = Color(0, 0, 255)
han = Color(63, 0, 255)
violet = Color(127, 0, 255)
purple = Color(191, 0, 255)
fuchsia = Color(255, 0, 255)
magenta = Color(255, 0, 191)
pink = Color(255, 0, 127)
crimson = Color(255, 0, 63)

# dark colors
dark_red = Color(191, 0, 0)
dark_flame = Color(191, 47, 0)
dark_orange = Color(191, 95, 0)
dark_amber = Color(191, 143, 0)
dark_yellow = Color(191, 191, 0)
dark_lime = Color(143, 191, 0)
dark_chartreuse = Color(95, 191, 0)
dark_green = Color(0, 191, 0)
dark_sea = Color(0, 191, 95)
dark_turquoise = Color(0, 191, 143)
dark_cyan = Color(0, 191, 191)
dark_sky = Color(0, 143, 191)
dark_azure = Color(0, 95, 191)
dark_blue = Color(0, 0, 191)
dark_han = Color(47, 0, 191)
dark_violet = Color(95, 0, 191)
dark_purple = Color(143, 0, 191)
dark_fuchsia = Color(191, 0, 191)
dark_magenta = Color(191, 0, 143)
dark_pink = Color(191, 0, 95)
dark_crimson = Color(191, 0, 47)

# darker colors
darker_red = Color(127, 0, 0)
darker_flame = Color(127, 31, 0)
darker_orange = Color(127, 63, 0)
darker_amber = Color(127, 95, 0)
darker_yellow = Color(127, 127, 0)
darker_lime = Color(95, 127, 0)
darker_chartreuse = Color(63, 127, 0)
darker_green = Color(0, 127, 0)
darker_sea = Color(0, 127, 63)
darker_turquoise = Color(0, 127, 95)
darker_cyan = Color(0, 127, 127)
darker_sky = Color(0, 95, 127)
darker_azure = Color(0, 63, 127)
darker_blue = Color(0, 0, 127)
darker_han = Color(31, 0, 127)
darker_violet = Color(63, 0, 127)
darker_purple = Color(95, 0, 127)
darker_fuchsia = Color(127, 0, 127)
darker_magenta = Color(127, 0, 95)
darker_pink = Color(127, 0, 63)
darker_crimson = Color(127, 0, 31)

# darkest colors
darkest_red = Color(63, 0, 0)
darkest_flame = Color(63, 15, 0)
darkest_orange = Color(63, 31, 0)
darkest_amber = Color(63, 47, 0)
darkest_yellow = Color(63, 63, 0)
darkest_lime = Color(47, 63, 0)
darkest_chartreuse = Color(31, 63, 0)
darkest_green = Color(0, 63, 0)
darkest_sea = Color(0, 63, 31)
darkest_turquoise = Color(0, 63, 47)
darkest_cyan = Color(0, 63, 63)
darkest_sky = Color(0, 47, 63)
darkest_azure = Color(0, 31, 63)
darkest_blue = Color(0, 0, 63)
darkest_han = Color(15, 0, 63)
darkest_violet = Color(31, 0, 63)
darkest_purple = Color(47, 0, 63)
darkest_fuchsia = Color(63, 0, 63)
darkest_magenta = Color(63, 0, 47)
darkest_pink = Color(63, 0, 31)
darkest_crimson = Color(63, 0, 15)

# light colors
light_red = Color(255, 114, 114)
light_flame = Color(255, 149, 114)
light_orange = Color(255, 184, 114)
light_amber = Color(255, 219, 114)
light_yellow = Color(255, 255, 114)
light_lime = Color(219, 255, 114)
light_chartreuse = Color(184, 255, 114)
light_green = Color(114, 255, 114)
light_sea = Color(114, 255, 184)
light_turquoise = Color(114, 255, 219)
light_cyan = Color(114, 255, 255)
light_sky = Color(114, 219, 255)
light_azure = Color(114, 184, 255)
light_blue = Color(114, 114, 255)
light_han = Color(149, 114, 255)
light_violet = Color(184, 114, 255)
light_purple = Color(219, 114, 255)
light_fuchsia = Color(255, 114, 255)
light_magenta = Color(255, 114, 219)
light_pink = Color(255, 114, 184)
light_crimson = Color(255, 114, 149)

# lighter colors
lighter_red = Color(255, 165, 165)
lighter_flame = Color(255, 188, 165)
lighter_orange = Color(255, 210, 165)
lighter_amber = Color(255, 232, 165)
lighter_yellow = Color(255, 255, 165)
lighter_lime = Color(232, 255, 165)
lighter_chartreuse = Color(210, 255, 165)
lighter_green = Color(165, 255, 165)
lighter_sea = Color(165, 255, 210)
lighter_turquoise = Color(165, 255, 232)
lighter_cyan = Color(165, 255, 255)
lighter_sky = Color(165, 232, 255)
lighter_azure = Color(165, 210, 255)
lighter_blue = Color(165, 165, 255)
lighter_han = Color(188, 165, 255)
lighter_violet = Color(210, 165, 255)
lighter_purple = Color(232, 165, 255)
lighter_fuchsia = Color(255, 165, 255)
lighter_magenta = Color(255, 165, 232)
lighter_pink = Color(255, 165, 210)
lighter_crimson = Color(255, 165, 188)

# lightest colors
lightest_red = Color(255, 191, 191)
lightest_flame = Color(255, 207, 191)
lightest_orange = Color(255, 223, 191)
lightest_amber = Color(255, 239, 191)
lightest_yellow = Color(255, 255, 191)
lightest_lime = Color(239, 255, 191)
lightest_chartreuse = Color(223, 255, 191)
lightest_green = Color(191, 255, 191)
lightest_sea = Color(191, 255, 223)
lightest_turquoise = Color(191, 255, 239)
lightest_cyan = Color(191, 255, 255)
lightest_sky = Color(191, 239, 255)
lightest_azure = Color(191, 223, 255)
lightest_blue = Color(191, 191, 255)
lightest_han = Color(207, 191, 255)
lightest_violet = Color(223, 191, 255)
lightest_purple = Color(239, 191, 255)
lightest_fuchsia = Color(255, 191, 255)
lightest_magenta = Color(255, 191, 239)
lightest_pink = Color(255, 191, 223)
lightest_crimson = Color(255, 191, 207)

# desaturated colors
desaturated_red = Color(127, 63, 63)
desaturated_flame = Color(127, 79, 63)
desaturated_orange = Color(127, 95, 63)
desaturated_amber = Color(127, 111, 63)
desaturated_yellow = Color(127, 127, 63)
desaturated_lime = Color(111, 127, 63)
desaturated_chartreuse = Color(95, 127, 63)
desaturated_green = Color(63, 127, 63)
desaturated_sea = Color(63, 127, 95)
desaturated_turquoise = Color(63, 127, 111)
desaturated_cyan = Color(63, 127, 127)
desaturated_sky = Color(63, 111, 127)
desaturated_azure = Color(63, 95, 127)
desaturated_blue = Color(63, 63, 127)
desaturated_han = Color(79, 63, 127)
desaturated_violet = Color(95, 63, 127)
desaturated_purple = Color(111, 63, 127)
desaturated_fuchsia = Color(127, 63, 127)
desaturated_magenta = Color(127, 63, 111)
desaturated_pink = Color(127, 63, 95)
desaturated_crimson = Color(127, 63, 79)

# metallic
brass = Color(191, 151, 96)
copper = Color(197, 136, 124)
gold = Color(229, 191, 0)
silver = Color(203, 203, 203)

# miscellaneous
celadon = Color(172, 255, 175)
peach = Color(255, 159, 127)

# color functions
_lib.TCOD_color_lerp.restype = Color


def color_lerp(c1, c2, a):
    return _lib.TCOD_color_lerp(c1, c2, c_float(a))


_lib.TCOD_color_set_HSV.restype = c_void
_lib.TCOD_color_set_HSV.argtypes = [POINTER(Color), c_float, c_float, c_float]


def color_set_hsv(c, h, s, v):
    _lib.TCOD_color_set_HSV(byref(c), c_float(h), c_float(s), c_float(v))


_lib.TCOD_color_get_HSV.restype = c_void
_lib.TCOD_color_get_HSV.argtypes = [Color, POINTER(c_float), POINTER(c_float), POINTER(c_float)]


def color_get_hsv(c):
    h = c_float()
    s = c_float()
    v = c_float()
    _lib.TCOD_color_get_HSV(c, byref(h), byref(s), byref(v))
    return h.value, s.value, v.value


_lib.TCOD_color_scale_HSV.restype = c_void
_lib.TCOD_color_scale_HSV.argtypes = [POINTER(Color), c_float, c_float]


def color_scale_HSV(c, scoef, vcoef):
    _lib.TCOD_color_scale_HSV(byref(c), c_float(scoef), c_float(vcoef))


_lib.TCOD_color_gen_map.restype = c_void
_lib.TCOD_color_gen_map.argtypes = [POINTER(Color), c_int, POINTER(Color), POINTER(c_int)]


def color_gen_map(colors, indexes):
    ccolors = (Color * len(colors))(*colors)
    cindexes = (c_int * len(indexes))(*indexes)
    cres = (Color * (max(indexes) + 1))()
    _lib.TCOD_color_gen_map(cres, len(colors), ccolors, cindexes)
    return cres


############################
# console module
############################
class Key(Structure):
    _fields_ = [
        ("vk", c_int),
        ("c", c_uint8),
        ("text", c_char * 32),
        ("pressed", c_bool),
        ("lalt", c_bool),
        ("lctrl", c_bool),
        ("lmeta", c_bool),
        ("ralt", c_bool),
        ("rctrl", c_bool),
        ("rmeta", c_bool),
        ("shift", c_bool),
    ]


class ConsoleBuffer:
    # simple console that allows direct (fast) access to cells. simplifies
    # use of the "fill" functions.
    def __init__(self, width, height, back_r=0, back_g=0, back_b=0, fore_r=0, fore_g=0, fore_b=0, char=" "):
        # initialize with given width and height. values to fill the buffer
        # are optional, defaults to black with no characters.
        n = width * height
        self.width = width
        self.height = height
        self.clear(back_r, back_g, back_b, fore_r, fore_g, fore_b, char)

    def clear(self, back_r=0, back_g=0, back_b=0, fore_r=0, fore_g=0, fore_b=0, char=" "):
        # clears the console. values to fill it with are optional, defaults
        # to black with no characters.
        n = self.width * self.height
        self.back_r = [back_r] * n
        self.back_g = [back_g] * n
        self.back_b = [back_b] * n
        self.fore_r = [fore_r] * n
        self.fore_g = [fore_g] * n
        self.fore_b = [fore_b] * n
        self.char = [ord(char)] * n

    def copy(self):
        # returns a copy of this ConsoleBuffer.
        other = ConsoleBuffer(0, 0)
        other.width = self.width
        other.height = self.height
        other.back_r = list(self.back_r)  # make explicit copies of all lists
        other.back_g = list(self.back_g)
        other.back_b = list(self.back_b)
        other.fore_r = list(self.fore_r)
        other.fore_g = list(self.fore_g)
        other.fore_b = list(self.fore_b)
        other.char = list(self.char)
        return other

    def set_fore(self, x, y, r, g, b, char):
        # set the character and foreground color of one cell.
        i = self.width * y + x
        self.fore_r[i] = int(r)
        self.fore_g[i] = int(g)
        self.fore_b[i] = int(b)
        self.char[i] = ord(char)

    def set_back(self, x, y, r, g, b):
        # set the background color of one cell.
        i = self.width * y + x
        self.back_r[i] = int(r)
        self.back_g[i] = int(g)
        self.back_b[i] = int(b)

    def set(self, x, y, back_r, back_g, back_b, fore_r, fore_g, fore_b, char):
        # set the background color, foreground color and character of one cell.
        i = self.width * y + x
        self.back_r[i] = int(back_r)
        self.back_g[i] = int(back_g)
        self.back_b[i] = int(back_b)
        self.fore_r[i] = int(fore_r)
        self.fore_g[i] = int(fore_g)
        self.fore_b[i] = int(fore_b)
        self.char[i] = ord(char)

    def blit(self, dest, fill_fore=True, fill_back=True):
        # use libtcod's "fill" functions to write the buffer to a console.
        if console_get_width(dest) != self.width or console_get_height(dest) != self.height:
            raise ValueError("ConsoleBuffer.blit: Destination console has an incorrect size.")

        s = struct.Struct("%di" % len(self.back_r))

        if fill_back:
            _lib.TCOD_console_fill_background(
                c_void_p(dest),
                (c_int * len(self.back_r))(*self.back_r),
                (c_int * len(self.back_g))(*self.back_g),
                (c_int * len(self.back_b))(*self.back_b),
            )

        if fill_fore:
            _lib.TCOD_console_fill_foreground(
                c_void_p(dest),
                (c_int * len(self.fore_r))(*self.fore_r),
                (c_int * len(self.fore_g))(*self.fore_g),
                (c_int * len(self.fore_b))(*self.fore_b),
            )
            _lib.TCOD_console_fill_char(c_void_p(dest), (c_int * len(self.char))(*self.char))


_lib.TCOD_console_is_fullscreen.restype = c_bool
_lib.TCOD_console_is_window_closed.restype = c_bool
_lib.TCOD_console_has_mouse_focus.restype = c_bool
_lib.TCOD_console_is_active.restype = c_bool
_lib.TCOD_console_get_default_background.restype = Color
_lib.TCOD_console_get_default_foreground.restype = Color
_lib.TCOD_console_get_char_background.restype = Color
_lib.TCOD_console_get_char_foreground.restype = Color
_lib.TCOD_console_get_fading_color.restype = Color
_lib.TCOD_console_is_key_pressed.restype = c_bool

# background rendering modes
BKGND_NONE = 0
BKGND_SET = 1
BKGND_MULTIPLY = 2
BKGND_LIGHTEN = 3
BKGND_DARKEN = 4
BKGND_SCREEN = 5
BKGND_COLOR_DODGE = 6
BKGND_COLOR_BURN = 7
BKGND_ADD = 8
BKGND_ADDA = 9
BKGND_BURN = 10
BKGND_OVERLAY = 11
BKGND_ALPH = 12
BKGND_DEFAULT = 13


def BKGND_ALPHA(a):
    return BKGND_ALPH | (int(a * 255) << 8)


def BKGND_ADDALPHA(a):
    return BKGND_ADDA | (int(a * 255) << 8)


# non blocking key events types
KEY_PRESSED = 1
KEY_RELEASED = 2
# key codes
KEY_NONE = 0
KEY_ESCAPE = 1
KEY_BACKSPACE = 2
KEY_TAB = 3
KEY_ENTER = 4
KEY_SHIFT = 5
KEY_CONTROL = 6
KEY_ALT = 7
KEY_PAUSE = 8
KEY_CAPSLOCK = 9
KEY_PAGEUP = 10
KEY_PAGEDOWN = 11
KEY_END = 12
KEY_HOME = 13
KEY_UP = 14
KEY_LEFT = 15
KEY_RIGHT = 16
KEY_DOWN = 17
KEY_PRINTSCREEN = 18
KEY_INSERT = 19
KEY_DELETE = 20
KEY_LWIN = 21
KEY_RWIN = 22
KEY_APPS = 23
KEY_0 = 24
KEY_1 = 25
KEY_2 = 26
KEY_3 = 27
KEY_4 = 28
KEY_5 = 29
KEY_6 = 30
KEY_7 = 31
KEY_8 = 32
KEY_9 = 33
KEY_KP0 = 34
KEY_KP1 = 35
KEY_KP2 = 36
KEY_KP3 = 37
KEY_KP4 = 38
KEY_KP5 = 39
KEY_KP6 = 40
KEY_KP7 = 41
KEY_KP8 = 42
KEY_KP9 = 43
KEY_KPADD = 44
KEY_KPSUB = 45
KEY_KPDIV = 46
KEY_KPMUL = 47
KEY_KPDEC = 48
KEY_KPENTER = 49
KEY_F1 = 50
KEY_F2 = 51
KEY_F3 = 52
KEY_F4 = 53
KEY_F5 = 54
KEY_F6 = 55
KEY_F7 = 56
KEY_F8 = 57
KEY_F9 = 58
KEY_F10 = 59
KEY_F11 = 60
KEY_F12 = 61
KEY_NUMLOCK = 62
KEY_SCROLLLOCK = 63
KEY_SPACE = 64
KEY_CHAR = 65
KEY_TEXT = 66
# special chars
# single walls
CHAR_HLINE = 196
CHAR_VLINE = 179
CHAR_NE = 191
CHAR_NW = 218
CHAR_SE = 217
CHAR_SW = 192
CHAR_TEEW = 180
CHAR_TEEE = 195
CHAR_TEEN = 193
CHAR_TEES = 194
CHAR_CROSS = 197
# double walls
CHAR_DHLINE = 205
CHAR_DVLINE = 186
CHAR_DNE = 187
CHAR_DNW = 201
CHAR_DSE = 188
CHAR_DSW = 200
CHAR_DTEEW = 185
CHAR_DTEEE = 204
CHAR_DTEEN = 202
CHAR_DTEES = 203
CHAR_DCROSS = 206
# blocks
CHAR_BLOCK1 = 176
CHAR_BLOCK2 = 177
CHAR_BLOCK3 = 178
# arrows
CHAR_ARROW_N = 24
CHAR_ARROW_S = 25
CHAR_ARROW_E = 26
CHAR_ARROW_W = 27
# arrows without tail
CHAR_ARROW2_N = 30
CHAR_ARROW2_S = 31
CHAR_ARROW2_E = 16
CHAR_ARROW2_W = 17
# double arrows
CHAR_DARROW_H = 29
CHAR_DARROW_V = 18
# GUI stuff
CHAR_CHECKBOX_UNSET = 224
CHAR_CHECKBOX_SET = 225
CHAR_RADIO_UNSET = 9
CHAR_RADIO_SET = 10
# sub-pixel resolution kit
CHAR_SUBP_NW = 226
CHAR_SUBP_NE = 227
CHAR_SUBP_N = 228
CHAR_SUBP_SE = 229
CHAR_SUBP_DIAG = 230
CHAR_SUBP_E = 231
CHAR_SUBP_SW = 232
# misc characters
CHAR_BULLET = 7
CHAR_BULLET_INV = 8
CHAR_BULLET_SQUARE = 254
CHAR_CENT = 189
CHAR_CLUB = 5
CHAR_COPYRIGHT = 184
CHAR_CURRENCY = 207
CHAR_DIAMOND = 4
CHAR_DIVISION = 246
CHAR_EXCLAM_DOUBLE = 19
CHAR_FEMALE = 12
CHAR_FUNCTION = 159
CHAR_GRADE = 248
CHAR_HALF = 171
CHAR_HEART = 3
CHAR_LIGHT = 15
CHAR_MALE = 11
CHAR_MULTIPLICATION = 158
CHAR_NOTE = 13
CHAR_NOTE_DOUBLE = 14
CHAR_ONE_QUARTER = 172
CHAR_PILCROW = 20
CHAR_POUND = 156
CHAR_POW1 = 251
CHAR_POW2 = 253
CHAR_POW3 = 252
CHAR_RESERVED = 169
CHAR_SECTION = 21
CHAR_SMILIE = 1
CHAR_SMILIE_INV = 2
CHAR_SPADE = 6
CHAR_THREE_QUARTERS = 243
CHAR_UMLAUT = 249
CHAR_YEN = 190
# font flags
FONT_LAYOUT_ASCII_INCOL = 1
FONT_LAYOUT_ASCII_INROW = 2
FONT_TYPE_GREYSCALE = 4
FONT_TYPE_GRAYSCALE = 4
FONT_LAYOUT_TCOD = 8
FONT_LAYOUT_CP437 = 16
# color control codes
COLCTRL_1 = 1
COLCTRL_2 = 2
COLCTRL_3 = 3
COLCTRL_4 = 4
COLCTRL_5 = 5
COLCTRL_NUMBER = 5
COLCTRL_FORE_RGB = 6
COLCTRL_BACK_RGB = 7
COLCTRL_STOP = 8
# renderers
RENDERER_GLSL = 0
RENDERER_OPENGL = 1
RENDERER_SDL = 2
RENDERER_SDL2 = 3
RENDERER_OPENGL2 = 4
NB_RENDERERS = 5
# alignment
LEFT = 0
RIGHT = 1
CENTER = 2


_lib.TCOD_quit.restype = c_void
_lib.TCOD_quit.argtypes = []

# initializing the console

_lib.TCOD_console_init_root.restype = c_int
_lib.TCOD_console_init_root.argtypes = [c_int, c_int, c_char_p, c_bool, c_uint]


def console_init_root(w, h, title, fullscreen=False, renderer=RENDERER_SDL):
    atexit.register(_lib.TCOD_quit)
    return _lib.TCOD_console_init_root(w, h, convert_to_ascii(title), fullscreen, renderer)


_lib.TCOD_console_set_custom_font.restype = c_void
_lib.TCOD_console_set_custom_font.argtypes = [c_char_p, c_int, c_int, c_int]


def console_set_custom_font(fontFile, flags=FONT_LAYOUT_ASCII_INCOL, nb_char_horiz=0, nb_char_vertic=0):
    _lib.TCOD_console_set_custom_font(convert_to_ascii(fontFile), flags, nb_char_horiz, nb_char_vertic)


_lib.TCOD_console_map_ascii_code_to_font.restype = c_void
_lib.TCOD_console_map_ascii_code_to_font.argtypes = [c_int, c_int, c_int]


def console_map_ascii_code_to_font(asciiCode, fontCharX, fontCharY):
    asciiCode = convert_to_ascii(asciiCode)
    if type(asciiCode) is bytes:
        _lib.TCOD_console_map_ascii_code_to_font(ord(asciiCode), fontCharX, fontCharY)
    else:
        _lib.TCOD_console_map_ascii_code_to_font(asciiCode, fontCharX, fontCharY)


_lib.TCOD_console_map_ascii_codes_to_font.restype = c_void
_lib.TCOD_console_map_ascii_codes_to_font.argtypes = [c_int, c_int, c_int, c_int]


def console_map_ascii_codes_to_font(firstAsciiCode, nbCodes, fontCharX, fontCharY):
    if type(firstAsciiCode) == str or type(firstAsciiCode) == bytes:
        _lib.TCOD_console_map_ascii_codes_to_font(ord(firstAsciiCode), nbCodes, fontCharX, fontCharY)
    else:
        _lib.TCOD_console_map_ascii_codes_to_font(firstAsciiCode, nbCodes, fontCharX, fontCharY)


_lib.TCOD_console_map_string_to_font.argtypes = [c_char_p, c_int, c_int]
_lib.TCOD_console_map_string_to_font_utf.argtypes = [c_wchar_p, c_int, c_int]


def console_map_string_to_font(s, fontCharX, fontCharY):
    # Python 3, utf is normal, so if they want utf behaviour call the other function.
    if type(s) is bytes or is_python_3:
        _lib.TCOD_console_map_string_to_font(convert_to_ascii(s), fontCharX, fontCharY)
    else:
        _lib.TCOD_console_map_string_to_font_utf(s, fontCharX, fontCharY)


def console_map_string_to_font_utf(s, fontCharX, fontCharY):
    _lib.TCOD_console_map_string_to_font_utf(s, fontCharX, fontCharY)


_lib.TCOD_console_is_fullscreen.restype = c_bool
_lib.TCOD_console_is_fullscreen.argtypes = []


def console_is_fullscreen():
    return _lib.TCOD_console_is_fullscreen()


_lib.TCOD_console_set_fullscreen.restype = c_void
_lib.TCOD_console_set_fullscreen.argtypes = [c_bool]


def console_set_fullscreen(fullscreen):
    _lib.TCOD_console_set_fullscreen(c_int(fullscreen))


_lib.TCOD_console_is_window_closed.restype = c_bool
_lib.TCOD_console_is_window_closed.argtypes = []


def console_is_window_closed():
    return _lib.TCOD_console_is_window_closed()


_lib.TCOD_console_has_mouse_focus.restype = c_bool
_lib.TCOD_console_has_mouse_focus.argtypes = []


def console_has_mouse_focus():
    return _lib.TCOD_console_has_mouse_focus()


_lib.TCOD_console_is_active.restype = c_bool
_lib.TCOD_console_is_active.argtypes = []


def console_is_active():
    return _lib.TCOD_console_is_active()


_lib.TCOD_console_set_window_title.restype = c_void
_lib.TCOD_console_set_window_title.argtypes = [c_char_p]


def console_set_window_title(title):
    _lib.TCOD_console_set_window_title(convert_to_ascii(title))


_lib.TCOD_console_credits_render.restype = c_bool


def console_credits():
    _lib.TCOD_console_credits()


_lib.TCOD_console_credits_reset.restype = c_void
_lib.TCOD_console_credits_reset.argtypes = []


def console_credits_reset():
    _lib.TCOD_console_credits_reset()


_lib.TCOD_console_credits_render.restype = c_bool
_lib.TCOD_console_credits_render.argtypes = [c_int, c_int, c_bool]


def console_credits_render(x, y, alpha):
    return _lib.TCOD_console_credits_render(x, y, c_int(alpha))


_lib.TCOD_console_flush.restype = c_int
_lib.TCOD_console_flush.argtypes = []


def console_flush():
    return _lib.TCOD_console_flush()


# drawing on a console

_lib.TCOD_console_set_default_background.restype = c_void
_lib.TCOD_console_set_default_background.argtypes = [c_void_p, Color]


def console_set_default_background(con, col):
    _lib.TCOD_console_set_default_background(con, col)


_lib.TCOD_console_set_default_foreground.restype = c_void
_lib.TCOD_console_set_default_foreground.argtypes = [c_void_p, Color]


def console_set_default_foreground(con, col):
    _lib.TCOD_console_set_default_foreground(con, col)


_lib.TCOD_console_clear.restype = c_void
_lib.TCOD_console_clear.argtypes = [c_void_p]


def console_clear(con):
    return _lib.TCOD_console_clear(con)


_lib.TCOD_console_put_char.restype = c_void
_lib.TCOD_console_put_char.argtypes = [c_void_p, c_int, c_int, c_int, c_int]


def console_put_char(con, x, y, c, flag=BKGND_DEFAULT):
    if type(c) == str or type(c) == bytes:
        _lib.TCOD_console_put_char(c_void_p(con), x, y, ord(c), flag)
    else:
        _lib.TCOD_console_put_char(c_void_p(con), x, y, c, flag)


_lib.TCOD_console_put_char_ex.restype = c_void
_lib.TCOD_console_put_char_ex.argtypes = [c_void_p, c_int, c_int, c_int, Color, Color]


def console_put_char_ex(con, x, y, c, fore, back):
    if type(c) == str or type(c) == bytes:
        _lib.TCOD_console_put_char_ex(c_void_p(con), x, y, ord(c), fore, back)
    else:
        _lib.TCOD_console_put_char_ex(c_void_p(con), x, y, c, fore, back)


_lib.TCOD_console_set_char_background.restype = c_void
_lib.TCOD_console_set_char_background.argtypes = [c_void_p, c_int, c_int, Color, c_int]


def console_set_char_background(con, x, y, col, flag=BKGND_SET):
    _lib.TCOD_console_set_char_background(con, x, y, col, flag)


_lib.TCOD_console_set_char_foreground.restype = c_void
_lib.TCOD_console_set_char_foreground.argtypes = [c_void_p, c_int, c_int, Color]


def console_set_char_foreground(con, x, y, col):
    _lib.TCOD_console_set_char_foreground(con, x, y, col)


_lib.TCOD_console_set_char.restype = c_void
_lib.TCOD_console_set_char.argtypes = [c_void_p, c_int, c_int, c_int]


def console_set_char(con, x, y, c):
    if type(c) == str or type(c) == bytes:
        _lib.TCOD_console_set_char(con, x, y, ord(c))
    else:
        _lib.TCOD_console_set_char(con, x, y, c)


_lib.TCOD_console_set_background_flag.restype = c_void
_lib.TCOD_console_set_background_flag.argtypes = [c_void_p, c_int]


def console_set_background_flag(con, flag):
    _lib.TCOD_console_set_background_flag(con, flag)


_lib.TCOD_console_get_background_flag.restype = c_int
_lib.TCOD_console_get_background_flag.argtypes = [c_void_p]


def console_get_background_flag(con):
    return _lib.TCOD_console_get_background_flag(con)


_lib.TCOD_console_set_alignment.restype = c_void
_lib.TCOD_console_set_alignment.argtypes = [c_void_p, c_int]


def console_set_alignment(con, alignment):
    _lib.TCOD_console_set_alignment(con, alignment)


_lib.TCOD_console_get_alignment.restype = c_int
_lib.TCOD_console_get_alignment.argtypes = [c_void_p]


def console_get_alignment(con):
    return _lib.TCOD_console_get_alignment(con)


_lib.TCOD_console_print.argtypes = [c_void_p, c_int, c_int, c_char_p]
_lib.TCOD_console_print_utf.argtypes = [c_void_p, c_int, c_int, c_wchar_p]


def console_print(con, x, y, fmt):
    _lib.TCOD_console_print_utf(con, x, y, _fmt_unicode(fmt))


_lib.TCOD_console_print_ex.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_char_p]
_lib.TCOD_console_print_ex_utf.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_wchar_p]


def console_print_ex(con, x, y, flag, alignment, fmt):
    _lib.TCOD_console_print_ex_utf(con, x, y, flag, alignment, _fmt_unicode(fmt))


_lib.TCOD_console_print_rect.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_char_p]
_lib.TCOD_console_print_rect_utf.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_wchar_p]


def console_print_rect(con, x, y, w, h, fmt):
    return _lib.TCOD_console_print_rect_utf(con, x, y, w, h, _fmt_unicode(fmt))


_lib.TCOD_console_print_rect_ex.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_int, c_int, c_char_p]
_lib.TCOD_console_print_rect_ex_utf.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_int, c_int, c_wchar_p]


def console_print_rect_ex(con, x, y, w, h, flag, alignment, fmt):
    return _lib.TCOD_console_print_rect_ex_utf(con, x, y, w, h, flag, alignment, _fmt_unicode(fmt))


_lib.TCOD_console_get_height_rect.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_char_p]
_lib.TCOD_console_get_height_rect_utf.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_wchar_p]


def console_get_height_rect(con, x, y, w, h, fmt):
    return _lib.TCOD_console_get_height_rect_utf(con, x, y, w, h, _fmt_unicode(fmt))


_lib.TCOD_console_rect.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_bool, c_int]


def console_rect(con, x, y, w, h, clr, flag=BKGND_DEFAULT):
    _lib.TCOD_console_rect(con, x, y, w, h, c_int(clr), flag)


_lib.TCOD_console_hline.argtypes = [c_void_p, c_int, c_int, c_int, c_int]


def console_hline(con, x, y, l, flag=BKGND_DEFAULT):
    _lib.TCOD_console_hline(con, x, y, l, flag)


_lib.TCOD_console_vline.argtypes = [c_void_p, c_int, c_int, c_int, c_int]


def console_vline(con, x, y, l, flag=BKGND_DEFAULT):
    _lib.TCOD_console_vline(con, x, y, l, flag)


_lib.TCOD_console_print_frame.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_int, c_int, c_char_p]


def console_print_frame(con, x, y, w, h, clear=True, flag=BKGND_DEFAULT, fmt=""):
    _lib.TCOD_console_print_frame(con, x, y, w, h, clear, flag, _fmt_bytes(fmt))


_lib.TCOD_console_set_color_control.restype = c_void
_lib.TCOD_console_set_color_control.argtypes = [c_void_p, Color, Color]


def console_set_color_control(con, fore, back):
    _lib.TCOD_console_set_color_control(con, fore, back)


_lib.TCOD_console_get_default_background.restype = Color
_lib.TCOD_console_get_default_background.argtypes = [c_void_p]


def console_get_default_background(con):
    return _lib.TCOD_console_get_default_background(con)


_lib.TCOD_console_get_default_foreground.restype = Color
_lib.TCOD_console_get_default_foreground.argtypes = [c_void_p]


def console_get_default_foreground(con):
    return _lib.TCOD_console_get_default_foreground(con)


_lib.TCOD_console_get_char_background.restype = Color
_lib.TCOD_console_get_char_background.argtypes = [c_void_p, c_int, c_int]


def console_get_char_background(con, x, y):
    return _lib.TCOD_console_get_char_background(con, x, y)


_lib.TCOD_console_get_char_foreground.restype = Color
_lib.TCOD_console_get_char_foreground.argtypes = [c_void_p, c_int, c_int]


def console_get_char_foreground(con, x, y):
    return _lib.TCOD_console_get_char_foreground(con, x, y)


_lib.TCOD_console_get_char.restype = c_int
_lib.TCOD_console_get_char.argtypes = [c_void_p, c_int, c_int]


def console_get_char(con, x, y):
    return _lib.TCOD_console_get_char(con, x, y)


_lib.TCOD_console_set_fade.restype = c_void
_lib.TCOD_console_set_fade.argtypes = [c_byte, Color]


def console_set_fade(fade, fadingColor):
    _lib.TCOD_console_set_fade(fade, fadingColor)


_lib.TCOD_console_get_fade.restype = c_byte
_lib.TCOD_console_get_fade.argtypes = []


def console_get_fade():
    return _lib.TCOD_console_get_fade()


_lib.TCOD_console_get_fading_color.restype = Color
_lib.TCOD_console_get_fading_color.argtypes = []


def console_get_fading_color():
    return _lib.TCOD_console_get_fading_color()


# handling keyboard input
def console_wait_for_keypress(flush):
    k = Key()
    _lib.TCOD_console_wait_for_keypress_wrapper(byref(k), c_bool(flush))
    return k


def console_check_for_keypress(flags=KEY_RELEASED):
    k = Key()
    _lib.TCOD_console_check_for_keypress_wrapper(byref(k), c_int(flags))
    return k


_lib.TCOD_console_is_key_pressed.restype = c_bool
_lib.TCOD_console_is_key_pressed.argtypes = [c_int]


def console_is_key_pressed(key):
    return _lib.TCOD_console_is_key_pressed(key)


# using offscreen consoles
_lib.TCOD_console_new.restype = c_void_p
_lib.TCOD_console_new.argtypes = [c_int, c_int]


def console_new(w, h):
    return _lib.TCOD_console_new(w, h)


_lib.TCOD_console_from_file.restype = c_void_p
_lib.TCOD_console_from_file.argtypes = [c_char_p]


def console_from_file(filename):
    return _lib.TCOD_console_from_file(convert_to_ascii(filename))


_lib.TCOD_console_get_width.restype = c_int
_lib.TCOD_console_get_width.argtypes = [c_void_p]


def console_get_width(con):
    return _lib.TCOD_console_get_width(con)


_lib.TCOD_console_get_height.restype = c_int
_lib.TCOD_console_get_height.argtypes = [c_void_p]


def console_get_height(con):
    return _lib.TCOD_console_get_height(con)


_lib.TCOD_console_blit.argtypes = [c_void_p, c_int, c_int, c_int, c_int, c_void_p, c_int, c_int, c_float, c_float]


def console_blit(src, x, y, w, h, dst, xdst, ydst, ffade=1.0, bfade=1.0):
    _lib.TCOD_console_blit(src, x, y, w, h, dst, xdst, ydst, c_float(ffade), c_float(bfade))


_lib.TCOD_console_set_key_color.argtypes = [c_void_p, Color]


def console_set_key_color(con, col):
    _lib.TCOD_console_set_key_color(c_void_p(con), col)


_lib.TCOD_console_set_dirty.restype = c_void
_lib.TCOD_console_set_dirty.argtypes = [c_int, c_int, c_int, c_int]


def console_set_dirty(x, y, w, h):
    return _lib.TCOD_console_set_dirty(x, y, w, h)


_lib.TCOD_console_delete.argtypes = [c_void_p]


def console_delete(con):
    _lib.TCOD_console_delete(con)


# fast color filling
_lib.TCOD_console_fill_foreground.restype = c_void
_lib.TCOD_console_fill_foreground.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int), POINTER(c_int)]


def console_fill_foreground(con, r, g, b):
    if len(r) != len(g) or len(r) != len(b):
        raise TypeError("R, G and B must all have the same size.")

    if (
        numpy_available
        and isinstance(r, numpy.ndarray)
        and isinstance(g, numpy.ndarray)
        and isinstance(b, numpy.ndarray)
    ):
        # numpy arrays, use numpy's ctypes functions
        r = numpy.ascontiguousarray(r, dtype=numpy.int32)
        g = numpy.ascontiguousarray(g, dtype=numpy.int32)
        b = numpy.ascontiguousarray(b, dtype=numpy.int32)
        cr = r.ctypes.data_as(POINTER(c_int))
        cg = g.ctypes.data_as(POINTER(c_int))
        cb = b.ctypes.data_as(POINTER(c_int))
    else:
        # otherwise convert using ctypes arrays
        cr = (c_int * len(r))(*r)
        cg = (c_int * len(g))(*g)
        cb = (c_int * len(b))(*b)

    _lib.TCOD_console_fill_foreground(c_void_p(con), cr, cg, cb)


_lib.TCOD_console_fill_background.restype = c_void
_lib.TCOD_console_fill_background.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int), POINTER(c_int)]


def console_fill_background(con, r, g, b):
    if len(r) != len(g) or len(r) != len(b):
        raise TypeError("R, G and B must all have the same size.")

    if (
        numpy_available
        and isinstance(r, numpy.ndarray)
        and isinstance(g, numpy.ndarray)
        and isinstance(b, numpy.ndarray)
    ):
        # numpy arrays, use numpy's ctypes functions
        r = numpy.ascontiguousarray(r, dtype=numpy.int32)
        g = numpy.ascontiguousarray(g, dtype=numpy.int32)
        b = numpy.ascontiguousarray(b, dtype=numpy.int32)
        cr = r.ctypes.data_as(POINTER(c_int))
        cg = g.ctypes.data_as(POINTER(c_int))
        cb = b.ctypes.data_as(POINTER(c_int))
    else:
        # otherwise convert using ctypes arrays
        cr = (c_int * len(r))(*r)
        cg = (c_int * len(g))(*g)
        cb = (c_int * len(b))(*b)

    _lib.TCOD_console_fill_background(c_void_p(con), cr, cg, cb)


_lib.TCOD_console_fill_char.restype = c_void
_lib.TCOD_console_fill_char.argtypes = [c_void_p, POINTER(c_int)]


def console_fill_char(con, arr):
    if numpy_available and isinstance(arr, numpy.ndarray):
        # numpy arrays, use numpy's ctypes functions
        arr = numpy.ascontiguousarray(arr, dtype=numpy.int32)
        carr = arr.ctypes.data_as(POINTER(c_int))
    else:
        carr = (c_int * len(arr))(*arr)

    _lib.TCOD_console_fill_char(c_void_p(con), carr)


_lib.TCOD_console_load_asc.restype = c_bool
_lib.TCOD_console_load_asc.argtypes = [c_void_p, c_char_p]


def console_load_asc(con, filename):
    return _lib.TCOD_console_load_asc(con, convert_to_ascii(filename))


_lib.TCOD_console_save_asc.restype = c_bool
_lib.TCOD_console_save_asc.argtypes = [c_void_p, c_char_p]


def console_save_asc(con, filename):
    return _lib.TCOD_console_save_asc(con, convert_to_ascii(filename))


_lib.TCOD_console_load_apf.restype = c_bool
_lib.TCOD_console_load_apf.argtypes = [c_void_p, c_char_p]


def console_load_apf(con, filename):
    return _lib.TCOD_console_load_apf(con, convert_to_ascii(filename))


_lib.TCOD_console_save_apf.restype = c_bool
_lib.TCOD_console_save_apf.argtypes = [c_void_p, c_char_p]


def console_save_apf(con, filename):
    return _lib.TCOD_console_save_apf(con, convert_to_ascii(filename))


_lib.TCOD_console_from_xp.restype = c_void_p
_lib.TCOD_console_from_xp.argtypes = [c_char_p]


def console_from_xp(filename):
    return _lib.TCOD_console_from_xp(filename.encode("utf-8"))


_lib.TCOD_console_load_xp.restype = c_bool
_lib.TCOD_console_load_xp.argtypes = [c_void_p, c_char_p]


def console_load_xp(con, filename):
    return _lib.TCOD_console_load_xp(con, filename.encode("utf-8"))


_lib.TCOD_console_save_xp.restype = c_bool
_lib.TCOD_console_save_xp.argtypes = [c_void_p, c_char_p, c_int]


def console_save_xp(con, filename, compress_level=9):
    return _lib.TCOD_console_save_xp(con, filename.encode("utf-8"), compress_level)


_lib.TCOD_console_list_from_xp.restype = c_void_p
_lib.TCOD_console_list_from_xp.argtypes = [c_char_p]


def console_list_load_xp(filename):
    tcod_list = _lib.TCOD_console_list_from_xp(filename.encode("utf-8"))
    if not tcod_list:
        return None
    try:
        python_list = []
        _lib.TCOD_list_reverse(tcod_list)
        while not _lib.TCOD_list_is_empty(tcod_list):
            python_list.append(_lib.TCOD_list_pop(tcod_list))
        return python_list
    finally:
        _lib.TCOD_list_delete(tcod_list)


_lib.TCOD_console_list_save_xp.restype = c_bool
_lib.TCOD_console_list_save_xp.argtypes = [c_void_p, c_char_p, c_int]


def console_list_save_xp(console_list, filename, compress_level=9):
    tcod_list = _lib.TCOD_list_new()
    try:
        for console in console_list:
            _lib.TCOD_list_push(tcod_list, console)
        return _lib.TCOD_console_list_save_xp(tcod_list, filename.encode("utf-8"), compress_level)
    finally:
        _lib.TCOD_list_delete(tcod_list)


############################
# sys module
############################

_lib.TCOD_sys_startup.restype = c_void
_lib.TCOD_sys_startup.argtypes = []


def sys_startup():
    _lib.TCOD_sys_startup()


_lib.TCOD_sys_shutdown.restype = c_void
_lib.TCOD_sys_shutdown.argtypes = []


def sys_shutdown():
    _lib.TCOD_sys_shutdown()


_lib.TCOD_sys_get_last_frame_length.restype = c_float
_lib.TCOD_sys_elapsed_seconds.restype = c_float

# high precision time functions
_lib.TCOD_sys_set_fps.restype = c_void
_lib.TCOD_sys_set_fps.argtypes = [c_int]


def sys_set_fps(fps):
    _lib.TCOD_sys_set_fps(fps)


_lib.TCOD_sys_get_fps.restype = c_int
_lib.TCOD_sys_get_fps.argtypes = []


def sys_get_fps():
    return _lib.TCOD_sys_get_fps()


_lib.TCOD_sys_get_last_frame_length.restype = c_float
_lib.TCOD_sys_get_last_frame_length.argtypes = []


def sys_get_last_frame_length():
    return _lib.TCOD_sys_get_last_frame_length()


_lib.TCOD_sys_sleep_milli.restype = c_void
_lib.TCOD_sys_sleep_milli.argtypes = [c_uint]


def sys_sleep_milli(val):
    _lib.TCOD_sys_sleep_milli(val)


_lib.TCOD_sys_elapsed_milli.restype = c_int
_lib.TCOD_sys_elapsed_milli.argtypes = []


def sys_elapsed_milli():
    return _lib.TCOD_sys_elapsed_milli()


_lib.TCOD_sys_elapsed_seconds.restype = c_float
_lib.TCOD_sys_elapsed_seconds.argtypes = []


def sys_elapsed_seconds():
    return _lib.TCOD_sys_elapsed_seconds()


_lib.TCOD_sys_set_renderer.restype = c_void
_lib.TCOD_sys_set_renderer.argtypes = [c_int]


def sys_set_renderer(renderer):
    _lib.TCOD_sys_set_renderer(renderer)


_lib.TCOD_sys_get_renderer.restype = c_int
_lib.TCOD_sys_get_renderer.argtypes = []


def sys_get_renderer():
    return _lib.TCOD_sys_get_renderer()


# easy screenshots

_lib.TCOD_sys_save_screenshot.restype = c_void
_lib.TCOD_sys_save_screenshot.argtypes = [c_char_p]


def sys_save_screenshot(name=0):
    _lib.TCOD_sys_save_screenshot(convert_to_ascii(name))


# clipboard support
# This maps to the SDL2 API, so only uses utf-8 for both Python 2 and 3.

_lib.TCOD_sys_clipboard_set.restype = c_bool
_lib.TCOD_sys_clipboard_set.argtypes = [c_char_p]


def sys_clipboard_set(text):
    return _lib.TCOD_sys_clipboard_set(text.encode("utf-8"))


_lib.TCOD_sys_clipboard_get.restype = c_char_p
_lib.TCOD_sys_clipboard_get.argtypes = []


def sys_clipboard_get():
    return _lib.TCOD_sys_clipboard_get().decode("utf-8")


# custom fullscreen resolution

_lib.TCOD_sys_force_fullscreen_resolution.restype = c_void
_lib.TCOD_sys_force_fullscreen_resolution.argtypes = [c_int, c_int]


def sys_force_fullscreen_resolution(width, height):
    _lib.TCOD_sys_force_fullscreen_resolution(width, height)


_lib.TCOD_sys_get_current_resolution.restype = c_void
_lib.TCOD_sys_get_current_resolution.argtypes = [POINTER(c_int), POINTER(c_int)]


def sys_get_current_resolution():
    w = c_int()
    h = c_int()
    _lib.TCOD_sys_get_current_resolution(byref(w), byref(h))
    return w.value, h.value


_lib.TCOD_sys_get_fullscreen_offsets.restype = c_void
_lib.TCOD_sys_get_fullscreen_offsets.argtypes = [POINTER(c_int), POINTER(c_int)]

_lib.TCOD_sys_get_char_size.restype = c_void
_lib.TCOD_sys_get_char_size.argtypes = [POINTER(c_int), POINTER(c_int)]


def sys_get_char_size():
    w = c_int()
    h = c_int()
    _lib.TCOD_sys_get_char_size(byref(w), byref(h))
    return w.value, h.value


# update font bitmap
_lib.TCOD_sys_update_char.restype = c_void
_lib.TCOD_sys_update_char.argtypes = [c_int, c_int, c_int, c_void_p, c_int, c_int]


def sys_update_char(asciiCode, fontx, fonty, img, x, y):
    _lib.TCOD_sys_update_char(asciiCode, fontx, fonty, img, x, y)


# custom SDL post renderer
SDL_RENDERER_FUNC = CFUNCTYPE(None, c_void_p)


def sys_register_SDL_renderer(callback):
    global sdl_renderer_func
    sdl_renderer_func = SDL_RENDERER_FUNC(callback)
    _lib.TCOD_sys_register_SDL_renderer(sdl_renderer_func)


# events
EVENT_NONE = 0
EVENT_KEY_PRESS = 1
EVENT_KEY_RELEASE = 2
EVENT_KEY = EVENT_KEY_PRESS | EVENT_KEY_RELEASE
EVENT_MOUSE_MOVE = 4
EVENT_MOUSE_PRESS = 8
EVENT_MOUSE_RELEASE = 16
EVENT_MOUSE = EVENT_MOUSE_MOVE | EVENT_MOUSE_PRESS | EVENT_MOUSE_RELEASE
EVENT_ANY = EVENT_KEY | EVENT_MOUSE

_lib.TCOD_sys_check_for_event.restype = c_int
_lib.TCOD_sys_check_for_event.argtypes = [c_int, c_void_p, c_void_p]


def sys_check_for_event(mask, k, m):
    return _lib.TCOD_sys_check_for_event(mask, byref(k), byref(m))


_lib.TCOD_sys_wait_for_event.restype = c_int
_lib.TCOD_sys_wait_for_event.argtypes = [c_int, c_void_p, c_void_p, c_bool]


def sys_wait_for_event(mask, k, m, flush):
    return _lib.TCOD_sys_wait_for_event(mask, byref(k), byref(m), flush)


############################
# line module
############################


def line_init(xo, yo, xd, yd):
    _lib.TCOD_line_init(xo, yo, xd, yd)


_lib.TCOD_line_step.restype = c_bool
_lib.TCOD_line_step.argtypes = [POINTER(c_int), POINTER(c_int)]


def line_step():
    x = c_int()
    y = c_int()
    ret = _lib.TCOD_line_step(byref(x), byref(y))
    if not ret:
        return x.value, y.value
    return None, None


_lib.TCOD_line.restype = c_bool


def line(xo, yo, xd, yd, py_callback):
    LINE_CBK_FUNC = CFUNCTYPE(c_bool, c_int, c_int)
    c_callback = LINE_CBK_FUNC(py_callback)
    return _lib.TCOD_line(xo, yo, xd, yd, c_callback)


_lib.TCOD_line_init_mt.restype = c_void
_lib.TCOD_line_init_mt.argtypes = [c_int, c_int, c_int, c_int, c_void_p]
_lib.TCOD_line_step_mt.restype = c_bool
_lib.TCOD_line_step_mt.argtypes = [POINTER(c_int), POINTER(c_int), c_void_p]


def line_iter(xo, yo, xd, yd):
    data = (c_int * 9)()  # struct TCOD_bresenham_data_t
    _lib.TCOD_line_init_mt(xo, yo, xd, yd, data)
    x = c_int(xo)
    y = c_int(yo)
    done = False
    while not done:
        yield x.value, y.value
        done = _lib.TCOD_line_step_mt(byref(x), byref(y), data)


############################
# image module
############################

_lib.TCOD_image_new.restype = c_void_p
_lib.TCOD_image_new.argtypes = [c_int, c_int]


def image_new(width, height):
    return _lib.TCOD_image_new(width, height)


_lib.TCOD_image_clear.restype = c_void
_lib.TCOD_image_clear.argtypes = [c_void_p, Color]


def image_clear(image, col):
    _lib.TCOD_image_clear(image, col)


_lib.TCOD_image_invert.restype = c_void
_lib.TCOD_image_invert.argtypes = [c_void_p]


def image_invert(image):
    _lib.TCOD_image_invert(image)


_lib.TCOD_image_hflip.restype = c_void
_lib.TCOD_image_hflip.argtypes = [c_void_p]


def image_hflip(image):
    _lib.TCOD_image_hflip(image)


_lib.TCOD_image_rotate90.restype = c_void
_lib.TCOD_image_rotate90.argtypes = [c_void_p, c_int]


def image_rotate90(image, num=1):
    _lib.TCOD_image_rotate90(image, num)


_lib.TCOD_image_vflip.restype = c_void
_lib.TCOD_image_vflip.argtypes = [c_void_p]


def image_vflip(image):
    _lib.TCOD_image_vflip(image)


_lib.TCOD_image_scale.restype = c_void
_lib.TCOD_image_scale.argtypes = [c_void_p, c_int, c_int]


def image_scale(image, neww, newh):
    _lib.TCOD_image_scale(image, neww, newh)


_lib.TCOD_image_set_key_color.restype = c_void
_lib.TCOD_image_set_key_color.argtypes = [c_void_p, Color]


def image_set_key_color(image, col):
    _lib.TCOD_image_set_key_color(image, col)


_lib.TCOD_image_get_alpha.restype = c_int
_lib.TCOD_image_get_alpha.argtypes = [c_void_p, c_int, c_int]


def image_get_alpha(image, x, y):
    return _lib.TCOD_image_get_alpha(image, c_int(x), c_int(y))


_lib.TCOD_image_is_pixel_transparent.restype = c_bool
_lib.TCOD_image_is_pixel_transparent.argtypes = [c_void_p, c_int, c_int]


def image_is_pixel_transparent(image, x, y):
    return _lib.TCOD_image_is_pixel_transparent(image, c_int(x), c_int(y))


_lib.TCOD_image_load.restype = c_void_p
_lib.TCOD_image_load.argtypes = [c_char_p]


def image_load(filename):
    return _lib.TCOD_image_load(convert_to_ascii(filename))


_lib.TCOD_image_from_console.restype = c_void_p
_lib.TCOD_image_from_console.argtypes = [c_void_p]


def image_from_console(console):
    return _lib.TCOD_image_from_console(console)


_lib.TCOD_image_refresh_console.restype = c_void
_lib.TCOD_image_refresh_console.argtypes = [c_void_p, c_void_p]


def image_refresh_console(image, console):
    _lib.TCOD_image_refresh_console(image, console)


_lib.TCOD_image_get_size.restype = c_void
_lib.TCOD_image_get_size.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int)]


def image_get_size(image):
    w = c_int()
    h = c_int()
    _lib.TCOD_image_get_size(image, byref(w), byref(h))
    return w.value, h.value


_lib.TCOD_image_get_pixel.restype = Color
_lib.TCOD_image_get_pixel.argtypes = [c_void_p, c_int, c_int]


def image_get_pixel(image, x, y):
    return _lib.TCOD_image_get_pixel(image, x, y)


_lib.TCOD_image_get_mipmap_pixel.restype = Color
_lib.TCOD_image_get_mipmap_pixel.argtypes = [c_void_p, c_float, c_float, c_float, c_float]


def image_get_mipmap_pixel(image, x0, y0, x1, y1):
    return _lib.TCOD_image_get_mipmap_pixel(image, c_float(x0), c_float(y0), c_float(x1), c_float(y1))


_lib.TCOD_image_put_pixel.restype = c_void
_lib.TCOD_image_put_pixel.argtypes = [c_void_p, c_int, c_int, Color]


def image_put_pixel(image, x, y, col):
    _lib.TCOD_image_put_pixel(image, x, y, col)


_lib.TCOD_image_blit.restype = c_void
_lib.TCOD_image_blit.argtypes = [c_void_p, c_void_p, c_float, c_float, c_int, c_float, c_float, c_float]


def image_blit(image, console, x, y, bkgnd_flag, scalex, scaley, angle):
    _lib.TCOD_image_blit(image, console, x, y, bkgnd_flag, scalex, scaley, angle)


_lib.TCOD_image_blit_rect.restype = c_void
_lib.TCOD_image_blit_rect.argtypes = [
    c_void_p,
    c_void_p,
    c_int,
    c_int,
    c_int,
    c_int,
]


def image_blit_rect(image, console, x, y, w, h, bkgnd_flag):
    _lib.TCOD_image_blit_rect(image, console, x, y, w, h, bkgnd_flag)


_lib.TCOD_image_blit_2x.restype = c_void
_lib.TCOD_image_blit_2x.argtypes = [c_void_p, c_void_p, c_int, c_int, c_int, c_int, c_int, c_int]


def image_blit_2x(image, console, dx, dy, sx=0, sy=0, w=-1, h=-1):
    _lib.TCOD_image_blit_2x(image, console, dx, dy, sx, sy, w, h)


_lib.TCOD_image_save.restype = c_void
_lib.TCOD_image_save.argtypes = [c_void_p, c_char_p]


def image_save(image, filename):
    _lib.TCOD_image_save(image, convert_to_ascii(filename))


_lib.TCOD_image_delete.restype = c_void
_lib.TCOD_image_delete.argtypes = [c_void_p]


def image_delete(image):
    _lib.TCOD_image_delete(image)


############################
# mouse module
############################
class Mouse(Structure):
    _fields_ = [
        ("x", c_int),
        ("y", c_int),
        ("dx", c_int),
        ("dy", c_int),
        ("cx", c_int),
        ("cy", c_int),
        ("dcx", c_int),
        ("dcy", c_int),
        ("lbutton", c_bool),
        ("rbutton", c_bool),
        ("mbutton", c_bool),
        ("lbutton_pressed", c_bool),
        ("rbutton_pressed", c_bool),
        ("mbutton_pressed", c_bool),
        ("wheel_up", c_bool),
        ("wheel_down", c_bool),
    ]


_lib.TCOD_mouse_is_cursor_visible.restype = c_bool

_lib.TCOD_mouse_show_cursor.restype = c_void
_lib.TCOD_mouse_show_cursor.argtypes = [c_bool]


def mouse_show_cursor(visible):
    _lib.TCOD_mouse_show_cursor(c_int(visible))


_lib.TCOD_mouse_is_cursor_visible.restype = c_bool
_lib.TCOD_mouse_is_cursor_visible.argtypes = []


def mouse_is_cursor_visible():
    return _lib.TCOD_mouse_is_cursor_visible()


_lib.TCOD_mouse_move.restype = c_void
_lib.TCOD_mouse_move.argtypes = [c_int, c_int]


def mouse_move(x, y):
    _lib.TCOD_mouse_move(x, y)


_lib.TCOD_mouse_get_status_wrapper.restype = c_void
_lib.TCOD_mouse_get_status_wrapper.argtypes = [c_void_p]


def mouse_get_status():
    mouse = Mouse()
    _lib.TCOD_mouse_get_status_wrapper(byref(mouse))
    return mouse


############################
# parser module
############################


class Dice(Structure):
    _fields_ = [
        ("nb_dices", c_int),
        ("nb_faces", c_int),
        ("multiplier", c_float),
        ("addsub", c_float),
    ]

    def __repr__(self):
        return "Dice(%d, %d, %s, %s)" % (self.nb_dices, self.nb_faces, self.multiplier, self.addsub)


class _CValue(Union):
    _fields_ = [
        ("c", c_uint8),
        ("i", c_int),
        ("f", c_float),
        ("s", c_char_p),
        # JBR03192012 See http://bugs.python.org/issue14354 for why these are not defined as their actual types
        ("col", c_uint8 * 3),
        ("dice", c_int * 4),
        ("custom", c_void_p),
    ]


_CFUNC_NEW_STRUCT = CFUNCTYPE(c_uint, c_void_p, c_char_p)
_CFUNC_NEW_FLAG = CFUNCTYPE(c_uint, c_char_p)
_CFUNC_NEW_PROPERTY = CFUNCTYPE(c_uint, c_char_p, c_int, _CValue)


class _CParserListener(Structure):
    _fields_ = [
        ("new_struct", _CFUNC_NEW_STRUCT),
        ("new_flag", _CFUNC_NEW_FLAG),
        ("new_property", _CFUNC_NEW_PROPERTY),
        ("end_struct", _CFUNC_NEW_STRUCT),
        ("error", _CFUNC_NEW_FLAG),
    ]


# property types
TYPE_NONE = 0
TYPE_BOOL = 1
TYPE_CHAR = 2
TYPE_INT = 3
TYPE_FLOAT = 4
TYPE_STRING = 5
TYPE_COLOR = 6
TYPE_DICE = 7
TYPE_VALUELIST00 = 8
TYPE_VALUELIST01 = 9
TYPE_VALUELIST02 = 10
TYPE_VALUELIST03 = 11
TYPE_VALUELIST04 = 12
TYPE_VALUELIST05 = 13
TYPE_VALUELIST06 = 14
TYPE_VALUELIST07 = 15
TYPE_VALUELIST08 = 16
TYPE_VALUELIST09 = 17
TYPE_VALUELIST10 = 18
TYPE_VALUELIST11 = 19
TYPE_VALUELIST12 = 20
TYPE_VALUELIST13 = 21
TYPE_VALUELIST14 = 22
TYPE_VALUELIST15 = 23
TYPE_LIST = 1024

_lib.TCOD_list_get.restype = c_void_p


def _convert_TCODList(clist, typ):
    res = list()
    for i in range(_lib.TCOD_list_size(c_void_p(clist))):
        elt = _lib.TCOD_list_get(c_void_p(clist), i)
        elt = cast(elt, c_void_p)
        if typ == TYPE_BOOL:
            elt = c_bool.from_buffer(elt).value
        elif typ == TYPE_CHAR:
            elt = c_char.from_buffer(elt).value
        elif typ == TYPE_INT:
            elt = c_int.from_buffer(elt).value
        elif typ == TYPE_FLOAT:
            elt = c_float.from_buffer(elt).value
        elif typ == TYPE_STRING or TYPE_VALUELIST15 >= typ >= TYPE_VALUELIST00:
            elt = cast(elt, c_char_p).value
        elif typ == TYPE_COLOR:
            elt = Color.from_buffer_copy(elt)
        elif typ == TYPE_DICE:
            # doesn't work
            elt = Dice.from_buffer_copy(elt)
        res.append(elt)
    return res


_lib.TCOD_parser_new.restype = c_void_p
_lib.TCOD_parser_new.argtypes = []


def parser_new():
    return _lib.TCOD_parser_new()


_lib.TCOD_parser_new_struct.restype = c_void_p
_lib.TCOD_parser_new_struct.argtypes = [c_void_p, c_char_p]


def parser_new_struct(parser, name):
    return _lib.TCOD_parser_new_struct(parser, convert_to_ascii(name))


_lib.TCOD_struct_add_flag.restype = c_void
_lib.TCOD_struct_add_flag.argtypes = [c_void_p, c_char_p]


def struct_add_flag(struct, name):
    _lib.TCOD_struct_add_flag(struct, convert_to_ascii(name))


_lib.TCOD_struct_add_property.restype = c_void
_lib.TCOD_struct_add_property.argtypes = [c_void_p, c_char_p, c_int, c_bool]


def struct_add_property(struct, name, typ, mandatory):
    _lib.TCOD_struct_add_property(struct, convert_to_ascii(name), typ, mandatory)


_lib.TCOD_struct_add_value_list.restype = c_void
_lib.TCOD_struct_add_value_list.argtypes = [c_void_p, c_char_p, POINTER(c_char_p), c_bool]


def struct_add_value_list(struct, name, value_list, mandatory):
    CARRAY = c_char_p * (len(value_list) + 1)
    cvalue_list = CARRAY()
    for i in range(len(value_list)):
        cvalue_list[i] = cast(convert_to_ascii(value_list[i]), c_char_p)
    cvalue_list[len(value_list)] = 0
    _lib.TCOD_struct_add_value_list(struct, convert_to_ascii(name), cvalue_list, mandatory)


_lib.TCOD_struct_add_value_list_sized.restype = c_void
_lib.TCOD_struct_add_value_list_sized.argtypes = [c_void_p, c_char_p, POINTER(c_char_p), c_int, c_bool]

_lib.TCOD_struct_add_list_property.restype = c_void
_lib.TCOD_struct_add_list_property.argtypes = [c_void_p, c_char_p, c_int, c_bool]


def struct_add_list_property(struct, name, typ, mandatory):
    _lib.TCOD_struct_add_list_property(struct, convert_to_ascii(name), typ, mandatory)


_lib.TCOD_struct_add_structure.restype = c_void
_lib.TCOD_struct_add_structure.argtypes = [c_void_p, c_void_p]


def struct_add_structure(struct, sub_struct):
    _lib.TCOD_struct_add_structure(struct, sub_struct)


_lib.TCOD_struct_get_name.restype = c_char_p
_lib.TCOD_struct_get_name.argtypes = [c_void_p]


def struct_get_name(struct):
    ret = _lib.TCOD_struct_get_name(struct)
    if is_python_3:
        return ret.decode("utf-8")
    return ret


_lib.TCOD_struct_is_mandatory.restype = c_bool
_lib.TCOD_struct_is_mandatory.argtypes = [c_void_p, c_char_p]


def struct_is_mandatory(struct, name):
    return _lib.TCOD_struct_is_mandatory(struct, convert_to_ascii(name))


_lib.TCOD_struct_get_type.restype = c_int
_lib.TCOD_struct_get_type.argtypes = [c_void_p, c_char_p]


def struct_get_type(struct, name):
    return _lib.TCOD_struct_get_type(struct, convert_to_ascii(name))


_lib.TCOD_parser_run.restype = c_void
_lib.TCOD_parser_run.argtypes = [c_void_p, c_char_p, c_void_p]


def parser_run(parser, filename, listener=0):
    if listener != 0:
        clistener = _CParserListener()

        def value_converter(name, typ, value):
            if typ == TYPE_BOOL:
                return listener.new_property(name, typ, value.c == 1)
            elif typ == TYPE_CHAR:
                return listener.new_property(name, typ, "%c" % (value.c & 0xFF))
            elif typ == TYPE_INT:
                return listener.new_property(name, typ, value.i)
            elif typ == TYPE_FLOAT:
                return listener.new_property(name, typ, value.f)
            elif typ == TYPE_STRING or TYPE_VALUELIST15 >= typ >= TYPE_VALUELIST00:
                return listener.new_property(name, typ, value.s)
            elif typ == TYPE_COLOR:
                col = cast(value.col, POINTER(Color)).contents
                return listener.new_property(name, typ, col)
            elif typ == TYPE_DICE:
                dice = cast(value.dice, POINTER(Dice)).contents
                return listener.new_property(name, typ, dice)
            elif typ & TYPE_LIST:
                return listener.new_property(name, typ, _convert_TCODList(value.custom, typ & 0xFF))
            return True

        clistener.new_struct = _CFUNC_NEW_STRUCT(listener.new_struct)
        clistener.new_flag = _CFUNC_NEW_FLAG(listener.new_flag)
        clistener.new_property = _CFUNC_NEW_PROPERTY(value_converter)
        clistener.end_struct = _CFUNC_NEW_STRUCT(listener.end_struct)
        clistener.error = _CFUNC_NEW_FLAG(listener.error)
        _lib.TCOD_parser_run(parser, convert_to_ascii(filename), byref(clistener))
    else:
        _lib.TCOD_parser_run(parser, convert_to_ascii(filename), 0)


_lib.TCOD_parser_delete.restype = c_void
_lib.TCOD_parser_delete.argtypes = [c_void_p]


def parser_delete(parser):
    _lib.TCOD_parser_delete(parser)


_lib.TCOD_parser_has_property.restype = c_bool
_lib.TCOD_parser_has_property.argtypes = [c_void_p, c_char_p]


def parser_has_property(parser, name):
    return _lib.TCOD_parser_has_property(parser, convert_to_ascii(name))


_lib.TCOD_parser_get_bool_property.restype = c_bool
_lib.TCOD_parser_get_bool_property.argtypes = [c_void_p, c_char_p]


def parser_get_bool_property(parser, name):
    return _lib.TCOD_parser_get_bool_property(parser, convert_to_ascii(name))


_lib.TCOD_parser_get_int_property.restype = c_int
_lib.TCOD_parser_get_int_property.argtypes = [c_void_p, c_char_p]


def parser_get_int_property(parser, name):
    return _lib.TCOD_parser_get_int_property(parser, convert_to_ascii(name))


_lib.TCOD_parser_get_char_property.restype = c_int
_lib.TCOD_parser_get_char_property.argtypes = [c_void_p, c_char_p]


def parser_get_char_property(parser, name):
    return "%c" % _lib.TCOD_parser_get_char_property(parser, convert_to_ascii(name))


_lib.TCOD_parser_get_float_property.restype = c_float
_lib.TCOD_parser_get_float_property.argtypes = [c_void_p, c_char_p]


def parser_get_float_property(parser, name):
    return _lib.TCOD_parser_get_float_property(parser, convert_to_ascii(name))


_lib.TCOD_parser_get_string_property.restype = c_char_p
_lib.TCOD_parser_get_string_property.argtypes = [c_void_p, c_char_p]


def parser_get_string_property(parser, name):
    ret = _lib.TCOD_parser_get_string_property(parser, convert_to_ascii(name))
    if is_python_3:
        return ret.decode("utf-8")
    return ret


_lib.TCOD_parser_get_color_property.restype = Color
_lib.TCOD_parser_get_color_property.argtypes = [c_void_p, c_char_p]


def parser_get_color_property(parser, name):
    return _lib.TCOD_parser_get_color_property(parser, convert_to_ascii(name))


_lib.TCOD_parser_get_dice_property_py.argtypes = [c_void_p, c_char_p, POINTER(Dice)]


def parser_get_dice_property(parser, name):
    d = Dice()
    _lib.TCOD_parser_get_dice_property_py(parser, convert_to_ascii(name), byref(d))
    return d


_lib.TCOD_parser_get_list_property.restype = c_void_p
_lib.TCOD_parser_get_list_property.argtypes = [c_void_p, c_char_p, c_int]


def parser_get_list_property(parser, name, typ):
    clist = _lib.TCOD_parser_get_list_property(parser, convert_to_ascii(name), typ)
    return _convert_TCODList(clist, typ)


_lib.TCOD_parser_get_custom_property.restype = c_void_p
_lib.TCOD_parser_get_custom_property.argtypes = [c_void_p, c_char_p]

############################
# random module
############################

RNG_MT = 0
RNG_CMWC = 1

DISTRIBUTION_LINEAR = 0
DISTRIBUTION_GAUSSIAN = 1
DISTRIBUTION_GAUSSIAN_RANGE = 2
DISTRIBUTION_GAUSSIAN_INVERSE = 3
DISTRIBUTION_GAUSSIAN_RANGE_INVERSE = 4

_lib.TCOD_random_get_instance.restype = c_void_p
_lib.TCOD_random_get_instance.argtypes = []


def random_get_instance():
    return _lib.TCOD_random_get_instance()


_lib.TCOD_random_new.restype = c_void_p
_lib.TCOD_random_new.argtypes = [c_int]


def random_new(algo=RNG_CMWC):
    return _lib.TCOD_random_new(algo)


_lib.TCOD_random_new_from_seed.restype = c_void_p
_lib.TCOD_random_new_from_seed.argtypes = [c_int, c_uint]


def random_new_from_seed(seed, algo=RNG_CMWC):
    return _lib.TCOD_random_new_from_seed(algo, seed)


_lib.TCOD_random_set_distribution.restype = c_void
_lib.TCOD_random_set_distribution.argtypes = [c_void_p, c_int]


def random_set_distribution(rnd, dist):
    _lib.TCOD_random_set_distribution(rnd, dist)


_lib.TCOD_random_get_int.restype = c_int
_lib.TCOD_random_get_int.argtypes = [c_void_p, c_int, c_int]


def random_get_int(rnd, mi, ma):
    return _lib.TCOD_random_get_int(rnd, mi, ma)


_lib.TCOD_random_get_float.restype = c_float
_lib.TCOD_random_get_float.argtypes = [c_void_p, c_float, c_float]


def random_get_float(rnd, mi, ma):
    return _lib.TCOD_random_get_float(rnd, mi, ma)


_lib.TCOD_random_get_double.restype = c_double
_lib.TCOD_random_get_double.argtypes = [c_void_p, c_double, c_double]


def random_get_double(rnd, mi, ma):
    return _lib.TCOD_random_get_double(rnd, mi, ma)


_lib.TCOD_random_get_int_mean.restype = c_int
_lib.TCOD_random_get_int_mean.argtypes = [c_void_p, c_int, c_int, c_int]


def random_get_int_mean(rnd, mi, ma, mean):
    return _lib.TCOD_random_get_int_mean(rnd, mi, ma, mean)


_lib.TCOD_random_get_float_mean.restype = c_float
_lib.TCOD_random_get_float_mean.argtypes = [c_void_p, c_float, c_float, c_float]


def random_get_float_mean(rnd, mi, ma, mean):
    return _lib.TCOD_random_get_float_mean(rnd, mi, ma, mean)


_lib.TCOD_random_get_double_mean.restype = c_double
_lib.TCOD_random_get_double_mean.argtypes = [c_void_p, c_double, c_double, c_double]


def random_get_double_mean(rnd, mi, ma, mean):
    return _lib.TCOD_random_get_double_mean(rnd, mi, ma, mean)


_lib.TCOD_random_dice_roll_s.restype = c_int
_lib.TCOD_random_dice_roll_s.argtypes = [c_void_p, c_char_p]


def random_dice_roll_s(rnd, s):
    return _lib.TCOD_random_dice_roll_s(rnd, convert_to_ascii(s))


_lib.TCOD_random_save.restype = c_void_p
_lib.TCOD_random_save.argtypes = [c_void_p]


def random_save(rnd):
    return _lib.TCOD_random_save(rnd)


_lib.TCOD_random_restore.restype = c_void
_lib.TCOD_random_restore.argtypes = [c_void_p, c_void_p]


def random_restore(rnd, backup):
    _lib.TCOD_random_restore(rnd, backup)


_lib.TCOD_random_delete.restype = c_void
_lib.TCOD_random_delete.argtypes = [c_void_p]


def random_delete(rnd):
    _lib.TCOD_random_delete(rnd)


############################
# noise module
############################

NOISE_DEFAULT_HURST = 0.5
NOISE_DEFAULT_LACUNARITY = 2.0

NOISE_DEFAULT = 0
NOISE_PERLIN = 1
NOISE_SIMPLEX = 2
NOISE_WAVELET = 4

_NOISE_PACKER_FUNC = (
    None,
    (c_float * 1),
    (c_float * 2),
    (c_float * 3),
    (c_float * 4),
)

_lib.TCOD_noise_new.restype = c_void_p
_lib.TCOD_noise_new.argtypes = [c_int, c_float, c_float, c_void_p]


def noise_new(dim, h=NOISE_DEFAULT_HURST, l=NOISE_DEFAULT_LACUNARITY, random=0):
    return _lib.TCOD_noise_new(dim, h, l, random)


_lib.TCOD_noise_set_type.restype = c_void
_lib.TCOD_noise_set_type.argtypes = [c_void_p, c_int]


def noise_set_type(n, typ):
    _lib.TCOD_noise_set_type(n, typ)


_lib.TCOD_noise_get.restype = c_float
_lib.TCOD_noise_get.argtypes = [c_void_p, POINTER(c_float)]

_lib.TCOD_noise_get_ex.restype = c_float
_lib.TCOD_noise_get_ex.argtypes = [c_void_p, POINTER(c_float), c_int]


def noise_get(n, f, typ=NOISE_DEFAULT):
    return _lib.TCOD_noise_get_ex(n, _NOISE_PACKER_FUNC[len(f)](*f), typ)


_lib.TCOD_noise_get_fbm.restype = c_float
_lib.TCOD_noise_get_fbm.argtypes = [c_void_p, POINTER(c_float), c_float]

_lib.TCOD_noise_get_fbm_ex.restype = c_float
_lib.TCOD_noise_get_fbm_ex.argtypes = [c_void_p, POINTER(c_float), c_float, c_int]


def noise_get_fbm(n, f, oc, typ=NOISE_DEFAULT):
    return _lib.TCOD_noise_get_fbm_ex(n, _NOISE_PACKER_FUNC[len(f)](*f), oc, typ)


_lib.TCOD_noise_get_turbulence.restype = c_float
_lib.TCOD_noise_get_turbulence.argtypes = [c_void_p, POINTER(c_float), c_float]

_lib.TCOD_noise_get_turbulence_ex.restype = c_float
_lib.TCOD_noise_get_turbulence_ex.argtypes = [c_void_p, POINTER(c_float), c_float, c_int]


def noise_get_turbulence(n, f, oc, typ=NOISE_DEFAULT):
    return _lib.TCOD_noise_get_turbulence_ex(n, _NOISE_PACKER_FUNC[len(f)](*f), oc, typ)


_lib.TCOD_noise_delete.restype = c_void
_lib.TCOD_noise_delete.argtypes = [c_void_p]


def noise_delete(n):
    _lib.TCOD_noise_delete(n)


############################
# fov module
############################
_lib.TCOD_map_is_in_fov.restype = c_bool
_lib.TCOD_map_is_transparent.restype = c_bool
_lib.TCOD_map_is_walkable.restype = c_bool

FOV_BASIC = 0
FOV_DIAMOND = 1
FOV_SHADOW = 2
FOV_PERMISSIVE_0 = 3
FOV_PERMISSIVE_1 = 4
FOV_PERMISSIVE_2 = 5
FOV_PERMISSIVE_3 = 6
FOV_PERMISSIVE_4 = 7
FOV_PERMISSIVE_5 = 8
FOV_PERMISSIVE_6 = 9
FOV_PERMISSIVE_7 = 10
FOV_PERMISSIVE_8 = 11
FOV_RESTRICTIVE = 12
NB_FOV_ALGORITHMS = 13


def FOV_PERMISSIVE(p):
    return FOV_PERMISSIVE_0 + p


_lib.TCOD_map_new.restype = c_void_p
_lib.TCOD_map_new.argtypes = [c_int, c_int]


def map_new(w, h):
    return _lib.TCOD_map_new(w, h)


_lib.TCOD_map_copy.restype = c_void
_lib.TCOD_map_copy.argtypes = [c_void_p, c_void_p]


def map_copy(source, dest):
    return _lib.TCOD_map_copy(source, dest)


_lib.TCOD_map_set_properties.restype = c_void
_lib.TCOD_map_set_properties.argtypes = [c_void_p, c_int, c_int, c_bool, c_bool]


def map_set_properties(m, x, y, isTrans, isWalk):
    _lib.TCOD_map_set_properties(m, x, y, c_int(isTrans), c_int(isWalk))


_lib.TCOD_map_clear.restype = c_void
_lib.TCOD_map_clear.argtypes = [c_void_p, c_bool, c_bool]


def map_clear(m, transparent=False, walkable=False):
    _lib.TCOD_map_clear(m, c_int(transparent), c_int(walkable))


_lib.TCOD_map_compute_fov.restype = c_void
_lib.TCOD_map_compute_fov.argtypes = [c_void_p, c_int, c_int, c_int, c_bool, c_int]


def map_compute_fov(m, x, y, radius=0, light_walls=True, algo=FOV_RESTRICTIVE):
    _lib.TCOD_map_compute_fov(m, x, y, c_int(radius), c_bool(light_walls), c_int(algo))


_lib.TCOD_map_set_in_fov.restype = c_void
_lib.TCOD_map_set_in_fov.argtypes = [c_void_p, c_int, c_int, c_bool]


def map_set_in_fov(m, x, y, fov):
    return _lib.TCOD_map_set_in_fov(m, x, y, fov)


_lib.TCOD_map_is_in_fov.restype = c_bool
_lib.TCOD_map_is_in_fov.argtypes = [c_void_p, c_int, c_int]


def map_is_in_fov(m, x, y):
    return _lib.TCOD_map_is_in_fov(m, x, y)


_lib.TCOD_map_is_transparent.restype = c_bool
_lib.TCOD_map_is_transparent.argtypes = [c_void_p, c_int, c_int]


def map_is_transparent(m, x, y):
    return _lib.TCOD_map_is_transparent(m, x, y)


_lib.TCOD_map_is_walkable.restype = c_bool
_lib.TCOD_map_is_walkable.argtypes = [c_void_p, c_int, c_int]


def map_is_walkable(m, x, y):
    return _lib.TCOD_map_is_walkable(m, x, y)


_lib.TCOD_map_delete.restype = c_void
_lib.TCOD_map_delete.argtypes = [c_void_p]


def map_delete(m):
    return _lib.TCOD_map_delete(m)


_lib.TCOD_map_get_width.restype = c_int
_lib.TCOD_map_get_width.argtypes = [c_void_p]


def map_get_width(map):
    return _lib.TCOD_map_get_width(map)


_lib.TCOD_map_get_height.restype = c_int
_lib.TCOD_map_get_height.argtypes = [c_void_p]


def map_get_height(map):
    return _lib.TCOD_map_get_height(map)


_lib.TCOD_map_get_nb_cells.restype = c_int
_lib.TCOD_map_get_nb_cells.argtypes = [c_void_p]


def map_get_nb_cells(map):
    return TCOD_map_get_nb_cells(map)


############################
# pathfinding module
############################

PATH_CBK_FUNC = CFUNCTYPE(c_float, c_int, c_int, c_int, c_int, py_object)

_lib.TCOD_path_new_using_map.restype = c_void_p
_lib.TCOD_path_new_using_map.argtypes = [c_void_p, c_float]


def path_new_using_map(m, dcost=1.41):
    return (_lib.TCOD_path_new_using_map(m, dcost), None)


_lib.TCOD_path_new_using_function.restype = c_void_p
_lib.TCOD_path_new_using_function.argtypes = [c_int, c_int, PATH_CBK_FUNC, py_object, c_float]


def path_new_using_function(w, h, func, userdata=0, dcost=1.41):
    cbk_func = PATH_CBK_FUNC(func)
    return (_lib.TCOD_path_new_using_function(w, h, cbk_func, userdata, dcost), cbk_func)


_lib.TCOD_path_compute.restype = c_bool
_lib.TCOD_path_compute.argtypes = [c_void_p, c_int, c_int, c_int, c_int]


def path_compute(p, ox, oy, dx, dy):
    return _lib.TCOD_path_compute(p[0], ox, oy, dx, dy)


_lib.TCOD_path_get_origin.restype = c_void
_lib.TCOD_path_get_origin.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int)]


def path_get_origin(p):
    x = c_int()
    y = c_int()
    _lib.TCOD_path_get_origin(p[0], byref(x), byref(y))
    return x.value, y.value


_lib.TCOD_path_get_destination.restype = c_void
_lib.TCOD_path_get_destination.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int)]


def path_get_destination(p):
    x = c_int()
    y = c_int()
    _lib.TCOD_path_get_destination(p[0], byref(x), byref(y))
    return x.value, y.value


_lib.TCOD_path_size.restype = c_int
_lib.TCOD_path_size.argtypes = [c_void_p]


def path_size(p):
    return _lib.TCOD_path_size(p[0])


_lib.TCOD_path_reverse.restype = c_void
_lib.TCOD_path_reverse.argtypes = [c_void_p]


def path_reverse(p):
    _lib.TCOD_path_reverse(p[0])


_lib.TCOD_path_get.restype = c_void
_lib.TCOD_path_get.argtypes = [c_void_p, c_int, POINTER(c_int), POINTER(c_int)]


def path_get(p, idx):
    x = c_int()
    y = c_int()
    _lib.TCOD_path_get(p[0], idx, byref(x), byref(y))
    return x.value, y.value


_lib.TCOD_path_is_empty.restype = c_bool
_lib.TCOD_path_is_empty.argtypes = [c_void_p]


def path_is_empty(p):
    return _lib.TCOD_path_is_empty(p[0])


_lib.TCOD_path_walk.restype = c_bool
_lib.TCOD_path_walk.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int), c_bool]


def path_walk(p, recompute):
    x = c_int()
    y = c_int()
    if _lib.TCOD_path_walk(p[0], byref(x), byref(y), c_int(recompute)):
        return x.value, y.value
    return None, None


_lib.TCOD_path_delete.restype = c_void
_lib.TCOD_path_delete.argtypes = [c_void_p]


def path_delete(p):
    _lib.TCOD_path_delete(p[0])


_lib.TCOD_dijkstra_new.restype = c_void_p
_lib.TCOD_dijkstra_new.argtypes = [c_void_p, c_float]


def dijkstra_new(m, dcost=1.41):
    return (_lib.TCOD_dijkstra_new(c_void_p(m), c_float(dcost)), None)


_lib.TCOD_dijkstra_new_using_function.restype = c_void_p
_lib.TCOD_dijkstra_new_using_function.argtypes = [c_int, c_int, PATH_CBK_FUNC, py_object, c_float]


def dijkstra_new_using_function(w, h, func, userdata=0, dcost=1.41):
    cbk_func = PATH_CBK_FUNC(func)
    return (_lib.TCOD_dijkstra_new_using_function(w, h, cbk_func, userdata, dcost), cbk_func)


_lib.TCOD_dijkstra_compute.restype = c_void
_lib.TCOD_dijkstra_compute.argtypes = [c_void_p, c_int, c_int]


def dijkstra_compute(p, ox, oy):
    _lib.TCOD_dijkstra_compute(p[0], c_int(ox), c_int(oy))


_lib.TCOD_dijkstra_path_set.restype = c_bool
_lib.TCOD_dijkstra_path_set.argtypes = [c_void_p, c_int, c_int]


def dijkstra_path_set(p, x, y):
    return _lib.TCOD_dijkstra_path_set(p[0], c_int(x), c_int(y))


_lib.TCOD_dijkstra_get_distance.restype = c_float
_lib.TCOD_dijkstra_get_distance.argtypes = [c_void_p, c_int, c_int]


def dijkstra_get_distance(p, x, y):
    return _lib.TCOD_dijkstra_get_distance(p[0], c_int(x), c_int(y))


_lib.TCOD_dijkstra_size.restype = c_int
_lib.TCOD_dijkstra_size.argtypes = [c_void_p]


def dijkstra_size(p):
    return _lib.TCOD_dijkstra_size(p[0])


_lib.TCOD_dijkstra_reverse.restype = c_void
_lib.TCOD_dijkstra_reverse.argtypes = [c_void_p]


def dijkstra_reverse(p):
    _lib.TCOD_dijkstra_reverse(p[0])


_lib.TCOD_dijkstra_get.restype = c_void
_lib.TCOD_dijkstra_get.argtypes = [c_void_p, c_int, POINTER(c_int), POINTER(c_int)]


def dijkstra_get(p, idx):
    x = c_int()
    y = c_int()
    _lib.TCOD_dijkstra_get(p[0], c_int(idx), byref(x), byref(y))
    return x.value, y.value


_lib.TCOD_dijkstra_is_empty.restype = c_bool
_lib.TCOD_dijkstra_is_empty.argtypes = [c_void_p]


def dijkstra_is_empty(p):
    return _lib.TCOD_dijkstra_is_empty(p[0])


_lib.TCOD_dijkstra_path_walk.restype = c_bool
_lib.TCOD_dijkstra_path_walk.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int)]


def dijkstra_path_walk(p):
    x = c_int()
    y = c_int()
    if _lib.TCOD_dijkstra_path_walk(p[0], byref(x), byref(y)):
        return x.value, y.value
    return None, None


_lib.TCOD_dijkstra_delete.restype = c_void
_lib.TCOD_dijkstra_delete.argtypes = [c_void_p]


def dijkstra_delete(p):
    _lib.TCOD_dijkstra_delete(p[0])


############################
# bsp module
############################
class _CBsp(Structure):
    _fields_ = [
        ("next", c_void_p),
        ("father", c_void_p),
        ("son", c_void_p),
        ("x", c_int),
        ("y", c_int),
        ("w", c_int),
        ("h", c_int),
        ("position", c_int),
        ("level", c_uint8),
        ("horizontal", c_bool),
    ]


BSP_CBK_FUNC = CFUNCTYPE(c_int, c_void_p, c_void_p)

# Python class encapsulating the _CBsp pointer
class Bsp(object):
    def __init__(self, cnode):
        pcbsp = cast(cnode, POINTER(_CBsp))
        self.p = pcbsp

    def getx(self):
        return self.p.contents.x

    def setx(self, value):
        self.p.contents.x = value

    x = property(getx, setx)

    def gety(self):
        return self.p.contents.y

    def sety(self, value):
        self.p.contents.y = value

    y = property(gety, sety)

    def getw(self):
        return self.p.contents.w

    def setw(self, value):
        self.p.contents.w = value

    w = property(getw, setw)

    def geth(self):
        return self.p.contents.h

    def seth(self, value):
        self.p.contents.h = value

    h = property(geth, seth)

    def getpos(self):
        return self.p.contents.position

    def setpos(self, value):
        self.p.contents.position = value

    position = property(getpos, setpos)

    def gethor(self):
        return self.p.contents.horizontal

    def sethor(self, value):
        self.p.contents.horizontal = value

    horizontal = property(gethor, sethor)

    def getlev(self):
        return self.p.contents.level

    def setlev(self, value):
        self.p.contents.level = value

    level = property(getlev, setlev)


_lib.TCOD_bsp_new.restype = c_void_p
_lib.TCOD_bsp_new.argtypes = [c_int, c_int, c_int, c_int]


def bsp_new(x, y, w, h):
    return _lib.TCOD_bsp_new(x, y, w, h)


_lib.TCOD_bsp_new_with_size.restype = POINTER(_CBsp)
_lib.TCOD_bsp_new_with_size.argtypes = [c_int, c_int, c_int, c_int]


def bsp_new_with_size(x, y, w, h):
    return Bsp(_lib.TCOD_bsp_new_with_size(x, y, w, h))


_lib.TCOD_bsp_split_once.restype = c_void
_lib.TCOD_bsp_split_once.argtypes = [c_void_p, c_bool, c_int]


def bsp_split_once(node, horizontal, position):
    _lib.TCOD_bsp_split_once(node.p, c_int(horizontal), position)


_lib.TCOD_bsp_split_recursive.restype = c_void
_lib.TCOD_bsp_split_recursive.argtypes = [
    c_void_p,
    c_void_p,
    c_int,
]


def bsp_split_recursive(node, randomizer, nb, minHSize, minVSize, maxHRatio, maxVRatio):
    _lib.TCOD_bsp_split_recursive(node.p, randomizer, nb, minHSize, minVSize, c_float(maxHRatio), c_float(maxVRatio))


_lib.TCOD_bsp_resize.restype = c_void
_lib.TCOD_bsp_resize.argtypes = [c_void_p, c_int, c_int, c_int, c_int]


def bsp_resize(node, x, y, w, h):
    _lib.TCOD_bsp_resize(node.p, x, y, w, h)


_lib.TCOD_bsp_left.restype = POINTER(_CBsp)
_lib.TCOD_bsp_left.argtypes = [c_void_p]


def bsp_left(node):
    return Bsp(_lib.TCOD_bsp_left(node.p))


_lib.TCOD_bsp_right.restype = POINTER(_CBsp)
_lib.TCOD_bsp_right.argtypes = [c_void_p]


def bsp_right(node):
    return Bsp(_lib.TCOD_bsp_right(node.p))


_lib.TCOD_bsp_father.restype = POINTER(_CBsp)
_lib.TCOD_bsp_father.argtypes = [c_void_p]


def bsp_father(node):
    return Bsp(_lib.TCOD_bsp_father(node.p))


_lib.TCOD_bsp_is_leaf.restype = c_bool
_lib.TCOD_bsp_is_leaf.argtypes = [c_void_p]


def bsp_is_leaf(node):
    return _lib.TCOD_bsp_is_leaf(node.p)


_lib.TCOD_bsp_contains.restype = c_bool
_lib.TCOD_bsp_contains.argtypes = [c_void_p, c_int, c_int]


def bsp_contains(node, cx, cy):
    return _lib.TCOD_bsp_contains(node.p, cx, cy)


_lib.TCOD_bsp_find_node.restype = POINTER(_CBsp)
_lib.TCOD_bsp_find_node.argtypes = [c_void_p, c_int, c_int]


def bsp_find_node(node, cx, cy):
    return Bsp(_lib.TCOD_bsp_find_node(node.p, cx, cy))


def _bsp_traverse(node, callback, userData, func):
    # convert the c node into a Python node
    # before passing it to the actual callback
    def node_converter(cnode, data):
        node = Bsp(cnode)
        return callback(node, data)

    cbk_func = BSP_CBK_FUNC(node_converter)
    func(node.p, cbk_func, userData)


def bsp_traverse_pre_order(node, callback, userData=0):
    _bsp_traverse(node, callback, userData, _lib.TCOD_bsp_traverse_pre_order)


def bsp_traverse_in_order(node, callback, userData=0):
    _bsp_traverse(node, callback, userData, _lib.TCOD_bsp_traverse_in_order)


def bsp_traverse_post_order(node, callback, userData=0):
    _bsp_traverse(node, callback, userData, _lib.TCOD_bsp_traverse_post_order)


def bsp_traverse_level_order(node, callback, userData=0):
    _bsp_traverse(node, callback, userData, _lib.TCOD_bsp_traverse_level_order)


def bsp_traverse_inverted_level_order(node, callback, userData=0):
    _bsp_traverse(node, callback, userData, _lib.TCOD_bsp_traverse_inverted_level_order)


_lib.TCOD_bsp_remove_sons.restype = c_void
_lib.TCOD_bsp_remove_sons.argtypes = [c_void_p]


def bsp_remove_sons(node):
    _lib.TCOD_bsp_remove_sons(node.p)


_lib.TCOD_bsp_delete.restype = c_void
_lib.TCOD_bsp_delete.argtypes = [c_void_p]


def bsp_delete(node):
    _lib.TCOD_bsp_delete(node.p)


############################
# heightmap module
############################
class _CHeightMap(Structure):
    _fields_ = [
        ("w", c_int),
        ("h", c_int),
        ("values", POINTER(c_float)),
    ]


class HeightMap(object):
    def __init__(self, chm):
        pchm = cast(chm, POINTER(_CHeightMap))
        self.p = pchm

    def getw(self):
        return self.p.contents.w

    def setw(self, value):
        self.p.contents.w = value

    w = property(getw, setw)

    def geth(self):
        return self.p.contents.h

    def seth(self, value):
        self.p.contents.h = value

    h = property(geth, seth)


_lib.TCOD_heightmap_new.restype = POINTER(_CHeightMap)
_lib.TCOD_heightmap_new.argtypes = [c_int, c_int]


def heightmap_new(w, h):
    phm = _lib.TCOD_heightmap_new(w, h)
    return HeightMap(phm)


_lib.TCOD_heightmap_set_value.restype = c_void
_lib.TCOD_heightmap_set_value.argtypes = [c_void_p, c_int, c_int, c_float]


def heightmap_set_value(hm, x, y, value):
    _lib.TCOD_heightmap_set_value(hm.p, x, y, c_float(value))


_lib.TCOD_heightmap_add.restype = c_void
_lib.TCOD_heightmap_add.argtypes = [c_void_p, c_float]


def heightmap_add(hm, value):
    _lib.TCOD_heightmap_add(hm.p, c_float(value))


_lib.TCOD_heightmap_scale.restype = c_void
_lib.TCOD_heightmap_scale.argtypes = [c_void_p, c_float]


def heightmap_scale(hm, value):
    _lib.TCOD_heightmap_scale(hm.p, c_float(value))


_lib.TCOD_heightmap_clear.restype = c_void
_lib.TCOD_heightmap_clear.argtypes = [c_void_p]


def heightmap_clear(hm):
    _lib.TCOD_heightmap_clear(hm.p)


_lib.TCOD_heightmap_clamp.restype = c_void
_lib.TCOD_heightmap_clamp.argtypes = [c_void_p, c_float, c_float]


def heightmap_clamp(hm, mi, ma):
    _lib.TCOD_heightmap_clamp(hm.p, c_float(mi), c_float(ma))


_lib.TCOD_heightmap_copy.restype = c_void
_lib.TCOD_heightmap_copy.argtypes = [c_void_p, c_void_p]


def heightmap_copy(hm1, hm2):
    _lib.TCOD_heightmap_copy(hm1.p, hm2.p)


_lib.TCOD_heightmap_normalize.restype = c_void
_lib.TCOD_heightmap_normalize.argtypes = [c_void_p, c_float, c_float]


def heightmap_normalize(hm, mi=0.0, ma=1.0):
    _lib.TCOD_heightmap_normalize(hm.p, c_float(mi), c_float(ma))


_lib.TCOD_heightmap_lerp_hm.restype = c_void
_lib.TCOD_heightmap_lerp_hm.argtypes = [c_void_p, c_void_p, c_void_p, c_float]


def heightmap_lerp_hm(hm1, hm2, hm3, coef):
    _lib.TCOD_heightmap_lerp_hm(hm1.p, hm2.p, hm3.p, c_float(coef))


_lib.TCOD_heightmap_add_hm.restype = c_void
_lib.TCOD_heightmap_add_hm.argtypes = [c_void_p, c_void_p, c_void_p]


def heightmap_add_hm(hm1, hm2, hm3):
    _lib.TCOD_heightmap_add_hm(hm1.p, hm2.p, hm3.p)


_lib.TCOD_heightmap_multiply_hm.restype = c_void
_lib.TCOD_heightmap_multiply_hm.argtypes = [c_void_p, c_void_p, c_void_p]


def heightmap_multiply_hm(hm1, hm2, hm3):
    _lib.TCOD_heightmap_multiply_hm(hm1.p, hm2.p, hm3.p)


_lib.TCOD_heightmap_add_hill.restype = c_void
_lib.TCOD_heightmap_add_hill.argtypes = [c_void_p, c_float, c_float, c_float, c_float]


def heightmap_add_hill(hm, x, y, radius, height):
    _lib.TCOD_heightmap_add_hill(hm.p, c_float(x), c_float(y), c_float(radius), c_float(height))


_lib.TCOD_heightmap_dig_hill.restype = c_void
_lib.TCOD_heightmap_dig_hill.argtypes = [c_void_p, c_float, c_float, c_float, c_float]


def heightmap_dig_hill(hm, x, y, radius, height):
    _lib.TCOD_heightmap_dig_hill(hm.p, c_float(x), c_float(y), c_float(radius), c_float(height))


_lib.TCOD_heightmap_mid_point_displacement.restype = c_void
_lib.TCOD_heightmap_mid_point_displacement.argtypes = [c_void_p, c_void_p, c_float]


def heightmap_mid_point_displacement(hm, rng, roughness):
    _lib.TCOD_heightmap_mid_point_displacement(hm.p, rng, roughness)


_lib.TCOD_heightmap_rain_erosion.restype = c_void
_lib.TCOD_heightmap_rain_erosion.argtypes = [c_void_p, c_int, c_float, c_float, c_void_p]


def heightmap_rain_erosion(hm, nbDrops, erosionCoef, sedimentationCoef, rnd=0):
    _lib.TCOD_heightmap_rain_erosion(hm.p, nbDrops, c_float(erosionCoef), c_float(sedimentationCoef), rnd)


_lib.TCOD_heightmap_kernel_transform.restype = c_void
_lib.TCOD_heightmap_kernel_transform.argtypes = [
    c_void_p,
    c_int,
    POINTER(c_int),
    POINTER(c_int),
    POINTER(c_float),
    c_float,
    c_float,
]


def heightmap_kernel_transform(hm, kernelsize, dx, dy, weight, minLevel, maxLevel):
    FARRAY = c_float * kernelsize
    IARRAY = c_int * kernelsize
    cdx = IARRAY(*dx)
    cdy = IARRAY(*dy)
    cweight = FARRAY(*weight)
    _lib.TCOD_heightmap_kernel_transform(hm.p, kernelsize, cdx, cdy, cweight, c_float(minLevel), c_float(maxLevel))


_lib.TCOD_heightmap_add_voronoi.restype = c_void
_lib.TCOD_heightmap_add_voronoi.argtypes = [c_void_p, c_int, c_int, POINTER(c_float), c_void_p]


def heightmap_add_voronoi(hm, nbPoints, nbCoef, coef, rnd=0):
    FARRAY = c_float * nbCoef
    ccoef = FARRAY(*coef)
    _lib.TCOD_heightmap_add_voronoi(hm.p, nbPoints, nbCoef, ccoef, rnd)


_lib.TCOD_heightmap_add_fbm.restype = c_void
_lib.TCOD_heightmap_add_fbm.argtypes = [
    c_void_p,
    c_void_p,
    c_float,
    c_float,
    c_float,
    c_float,
    c_float,
    c_float,
    c_float,
]


def heightmap_add_fbm(hm, noise, mulx, muly, addx, addy, octaves, delta, scale):
    _lib.TCOD_heightmap_add_fbm(
        hm.p,
        noise,
        c_float(mulx),
        c_float(muly),
        c_float(addx),
        c_float(addy),
        c_float(octaves),
        c_float(delta),
        c_float(scale),
    )


_lib.TCOD_heightmap_scale_fbm.restype = c_void
_lib.TCOD_heightmap_scale_fbm.argtypes = [
    c_void_p,
    c_void_p,
    c_float,
    c_float,
    c_float,
    c_float,
    c_float,
    c_float,
    c_float,
]


def heightmap_scale_fbm(hm, noise, mulx, muly, addx, addy, octaves, delta, scale):
    _lib.TCOD_heightmap_scale_fbm(
        hm.p,
        noise,
        c_float(mulx),
        c_float(muly),
        c_float(addx),
        c_float(addy),
        c_float(octaves),
        c_float(delta),
        c_float(scale),
    )


_lib.TCOD_heightmap_islandify.restype = c_void
_lib.TCOD_heightmap_islandify.argtypes = [c_void_p, c_float, c_void_p]


def heightmap_islandify(hm, sealevel, rnd):
    return TCOD_heightmap_islandify(hm, sealevel, rnd)


_lib.TCOD_heightmap_dig_bezier.restype = c_void
_lib.TCOD_heightmap_dig_bezier.argtypes = [c_void_p, POINTER(c_int), POINTER(c_int), c_float, c_float, c_float, c_float]


def heightmap_dig_bezier(hm, px, py, startRadius, startDepth, endRadius, endDepth):
    IARRAY = c_int * 4
    cpx = IARRAY(*px)
    cpy = IARRAY(*py)
    _lib.TCOD_heightmap_dig_bezier(
        hm.p, cpx, cpy, c_float(startRadius), c_float(startDepth), c_float(endRadius), c_float(endDepth)
    )


_lib.TCOD_heightmap_get_value.restype = c_float
_lib.TCOD_heightmap_get_value.argtypes = [c_void_p, c_int, c_int]


def heightmap_get_value(hm, x, y):
    return _lib.TCOD_heightmap_get_value(hm.p, x, y)


_lib.TCOD_heightmap_get_interpolated_value.restype = c_float
_lib.TCOD_heightmap_get_interpolated_value.argtypes = [c_void_p, c_float, c_float]


def heightmap_get_interpolated_value(hm, x, y):
    return _lib.TCOD_heightmap_get_interpolated_value(hm.p, c_float(x), c_float(y))


_lib.TCOD_heightmap_get_slope.restype = c_float
_lib.TCOD_heightmap_get_slope.argtypes = [c_void_p, c_int, c_int]


def heightmap_get_slope(hm, x, y):
    return _lib.TCOD_heightmap_get_slope(hm.p, x, y)


_lib.TCOD_heightmap_get_normal.restype = c_void
_lib.TCOD_heightmap_get_normal.argtypes = [c_void_p, c_float, c_float, POINTER(c_float), c_float]


def heightmap_get_normal(hm, x, y, waterLevel):
    FARRAY = c_float * 3
    cn = FARRAY()
    _lib.TCOD_heightmap_get_normal(hm.p, c_float(x), c_float(y), cn, c_float(waterLevel))
    return cn[0], cn[1], cn[2]


_lib.TCOD_heightmap_count_cells.restype = c_int
_lib.TCOD_heightmap_count_cells.argtypes = [c_void_p, c_float, c_float]


def heightmap_count_cells(hm, mi, ma):
    return _lib.TCOD_heightmap_count_cells(hm.p, c_float(mi), c_float(ma))


_lib.TCOD_heightmap_has_land_on_border.restype = c_bool
_lib.TCOD_heightmap_has_land_on_border.argtypes = [c_void_p, c_float]


def heightmap_has_land_on_border(hm, waterlevel):
    return _lib.TCOD_heightmap_has_land_on_border(hm.p, c_float(waterlevel))


_lib.TCOD_heightmap_get_minmax.restype = c_void
_lib.TCOD_heightmap_get_minmax.argtypes = [c_void_p, POINTER(c_float), POINTER(c_float)]


def heightmap_get_minmax(hm):
    mi = c_float()
    ma = c_float()
    _lib.TCOD_heightmap_get_minmax(hm.p, byref(mi), byref(ma))
    return mi.value, ma.value


_lib.TCOD_heightmap_delete.restype = c_void
_lib.TCOD_heightmap_delete.argtypes = [c_void_p]


def heightmap_delete(hm):
    _lib.TCOD_heightmap_delete(hm.p)


############################
# name generator module
############################

_lib.TCOD_namegen_parse.restype = c_void
_lib.TCOD_namegen_parse.argtypes = [c_char_p, c_void_p]


def namegen_parse(filename, rnd=0):
    _lib.TCOD_namegen_parse(convert_to_ascii(filename), rnd)


_lib.TCOD_namegen_generate.restype = c_char_p
_lib.TCOD_namegen_generate.argtypes = [c_char_p, c_bool]


def namegen_generate(name):
    ret = _lib.TCOD_namegen_generate(convert_to_ascii(name), 0)
    if is_python_3:
        return ret.decode("utf-8")
    return ret


_lib.TCOD_namegen_generate_custom.restype = c_char_p
_lib.TCOD_namegen_generate_custom.argtypes = [c_char_p, c_char_p, c_bool]


def namegen_generate_custom(name, rule):
    ret = _lib.TCOD_namegen_generate(convert_to_ascii(name), convert_to_ascii(rule), 0)
    if is_python_3:
        return ret.decode("utf-8")
    return ret


_lib.TCOD_namegen_get_sets.restype = c_void_p
_lib.TCOD_namegen_get_sets.argtypes = []


def namegen_get_sets():
    nb = _lib.TCOD_namegen_get_nb_sets_wrapper()
    SARRAY = c_char_p * nb
    setsa = SARRAY()
    _lib.TCOD_namegen_get_sets_wrapper(setsa)
    if is_python_3:
        return list(v.decode("utf-8") for v in setsa)
    return list(setsa)


_lib.TCOD_namegen_destroy.restype = c_void
_lib.TCOD_namegen_destroy.argtypes = []


def namegen_destroy():
    _lib.TCOD_namegen_destroy()


_lib.TCOD_lex_new_intern.restype = c_void_p
_lib.TCOD_lex_new_intern.argtypes = []

_lib.TCOD_lex_new.restype = c_void_p
_lib.TCOD_lex_new.argtypes = [
    POINTER(c_char_p),
    POINTER(c_char_p),
    c_char_p,
]

_lib.TCOD_lex_delete.restype = c_void
_lib.TCOD_lex_delete.argtypes = [c_void_p]

_lib.TCOD_lex_set_data_buffer.restype = c_void
_lib.TCOD_lex_set_data_buffer.argtypes = [c_void_p, c_char_p]

_lib.TCOD_lex_set_data_file.restype = c_bool
_lib.TCOD_lex_set_data_file.argtypes = [c_void_p, c_char_p]

_lib.TCOD_lex_parse.restype = c_int
_lib.TCOD_lex_parse.argtypes = [c_void_p]

_lib.TCOD_lex_parse_until_token_type.restype = c_int
_lib.TCOD_lex_parse_until_token_type.argtypes = [c_void_p, c_int]

_lib.TCOD_lex_parse_until_token_value.restype = c_int
_lib.TCOD_lex_parse_until_token_value.argtypes = [c_void_p, c_char_p]

_lib.TCOD_lex_expect_token_type.restype = c_bool
_lib.TCOD_lex_expect_token_type.argtypes = [c_void_p, c_int]

_lib.TCOD_lex_expect_token_value.restype = c_bool
_lib.TCOD_lex_expect_token_value.argtypes = [c_void_p, c_int, c_char_p]

_lib.TCOD_lex_savepoint.restype = c_void
_lib.TCOD_lex_savepoint.argtypes = [c_void_p, c_void_p]

_lib.TCOD_lex_restore.restype = c_void
_lib.TCOD_lex_restore.argtypes = [c_void_p, c_void_p]

_lib.TCOD_lex_get_last_javadoc.restype = c_char_p
_lib.TCOD_lex_get_last_javadoc.argtypes = [c_void_p]

_lib.TCOD_lex_get_token_name.restype = c_char_p
_lib.TCOD_lex_get_token_name.argtypes = [c_int]

_lib.TCOD_lex_hextoint.restype = c_int
_lib.TCOD_lex_hextoint.argtypes = [c_char]

_lib.TCOD_sys_load_image.restype = c_void_p
_lib.TCOD_sys_load_image.argtypes = [c_char_p]

_lib.TCOD_list_new.restype = c_void_p
_lib.TCOD_list_new.argtypes = []

_lib.TCOD_list_allocate.restype = c_void_p
_lib.TCOD_list_allocate.argtypes = [c_int]

_lib.TCOD_list_duplicate.restype = c_void_p
_lib.TCOD_list_duplicate.argtypes = [c_void_p]

_lib.TCOD_list_delete.restype = c_void
_lib.TCOD_list_delete.argtypes = [c_void_p]

_lib.TCOD_list_push.restype = c_void
_lib.TCOD_list_push.argtypes = [c_void_p, c_void_p]

_lib.TCOD_list_pop.restype = c_void_p
_lib.TCOD_list_pop.argtypes = [c_void_p]

_lib.TCOD_list_peek.restype = c_void_p
_lib.TCOD_list_peek.argtypes = [c_void_p]

_lib.TCOD_list_add_all.restype = c_void
_lib.TCOD_list_add_all.argtypes = [c_void_p, c_void_p]

_lib.TCOD_list_get.restype = c_void_p
_lib.TCOD_list_get.argtypes = [c_void_p, c_int]

_lib.TCOD_list_set.restype = c_void
_lib.TCOD_list_set.argtypes = [c_void_p, c_void_p, c_int]

_lib.TCOD_list_begin.restype = POINTER(c_void_p)
_lib.TCOD_list_begin.argtypes = [c_void_p]

_lib.TCOD_list_end.restype = POINTER(c_void_p)
_lib.TCOD_list_end.argtypes = [c_void_p]

_lib.TCOD_list_reverse.restype = c_void
_lib.TCOD_list_reverse.argtypes = [c_void_p]

_lib.TCOD_list_remove_iterator.restype = POINTER(c_void_p)
_lib.TCOD_list_remove_iterator.argtypes = [c_void_p, POINTER(c_void_p)]

_lib.TCOD_list_remove.restype = c_void
_lib.TCOD_list_remove.argtypes = [c_void_p, c_void_p]

_lib.TCOD_list_remove_iterator_fast.restype = POINTER(c_void_p)
_lib.TCOD_list_remove_iterator_fast.argtypes = [c_void_p, POINTER(c_void_p)]

_lib.TCOD_list_remove_fast.restype = c_void
_lib.TCOD_list_remove_fast.argtypes = [c_void_p, c_void_p]

_lib.TCOD_list_contains.restype = c_bool
_lib.TCOD_list_contains.argtypes = [c_void_p, c_void_p]

_lib.TCOD_list_clear.restype = c_void
_lib.TCOD_list_clear.argtypes = [c_void_p]

_lib.TCOD_list_clear_and_delete.restype = c_void
_lib.TCOD_list_clear_and_delete.argtypes = [c_void_p]

_lib.TCOD_list_size.restype = c_int
_lib.TCOD_list_size.argtypes = [c_void_p]

_lib.TCOD_list_insert_before.restype = POINTER(c_void_p)
_lib.TCOD_list_insert_before.argtypes = [c_void_p, c_void_p, c_int]

_lib.TCOD_list_is_empty.restype = c_bool
_lib.TCOD_list_is_empty.argtypes = [c_void_p]

_lib.TCOD_sys_create_directory.restype = c_bool
_lib.TCOD_sys_create_directory.argtypes = [c_char_p]

_lib.TCOD_sys_delete_file.restype = c_bool
_lib.TCOD_sys_delete_file.argtypes = [c_char_p]

_lib.TCOD_sys_delete_directory.restype = c_bool
_lib.TCOD_sys_delete_directory.argtypes = [c_char_p]

_lib.TCOD_sys_is_directory.restype = c_bool
_lib.TCOD_sys_is_directory.argtypes = [c_char_p]

_lib.TCOD_sys_get_directory_content.restype = c_void_p
_lib.TCOD_sys_get_directory_content.argtypes = [c_char_p, c_char_p]

_lib.TCOD_sys_file_exists.restype = c_bool
#    lib.TCOD_sys_file_exists.argtypes=[c_char_p , ...]

_lib.TCOD_sys_get_num_cores.restype = c_int
_lib.TCOD_sys_get_num_cores.argtypes = []

_lib.TCOD_thread_wait.restype = c_void
_lib.TCOD_thread_wait.argtypes = [c_void_p]

_lib.TCOD_mutex_new.restype = c_void_p
_lib.TCOD_mutex_new.argtypes = []

_lib.TCOD_mutex_in.restype = c_void
_lib.TCOD_mutex_in.argtypes = [c_void_p]

_lib.TCOD_mutex_out.restype = c_void
_lib.TCOD_mutex_out.argtypes = [c_void_p]

_lib.TCOD_mutex_delete.restype = c_void
_lib.TCOD_mutex_delete.argtypes = [c_void_p]

_lib.TCOD_semaphore_new.restype = c_void_p
_lib.TCOD_semaphore_new.argtypes = [c_int]

_lib.TCOD_semaphore_lock.restype = c_void
_lib.TCOD_semaphore_lock.argtypes = [c_void_p]

_lib.TCOD_semaphore_unlock.restype = c_void
_lib.TCOD_semaphore_unlock.argtypes = [c_void_p]

_lib.TCOD_semaphore_delete.restype = c_void
_lib.TCOD_semaphore_delete.argtypes = [c_void_p]

_lib.TCOD_condition_new.restype = c_void_p
_lib.TCOD_condition_new.argtypes = []

_lib.TCOD_condition_signal.restype = c_void
_lib.TCOD_condition_signal.argtypes = [c_void_p]

_lib.TCOD_condition_broadcast.restype = c_void
_lib.TCOD_condition_broadcast.argtypes = [c_void_p]

_lib.TCOD_condition_wait.restype = c_void
_lib.TCOD_condition_wait.argtypes = [c_void_p, c_void_p]

_lib.TCOD_condition_delete.restype = c_void
_lib.TCOD_condition_delete.argtypes = [c_void_p]

_lib.TCOD_tree_new.restype = c_void_p
_lib.TCOD_tree_new.argtypes = []

_lib.TCOD_tree_add_son.restype = c_void
_lib.TCOD_tree_add_son.argtypes = [c_void_p, c_void_p]

_lib.TCOD_text_init.restype = c_void_p
_lib.TCOD_text_init.argtypes = [c_int, c_int, c_int, c_int, c_int]

_lib.TCOD_text_set_properties.restype = c_void
_lib.TCOD_text_set_properties.argtypes = [c_void_p, c_int, c_int, c_char_p, c_int]

_lib.TCOD_text_set_colors.restype = c_void
_lib.TCOD_text_set_colors.argtypes = [c_void_p, c_int, c_int, c_float]

_lib.TCOD_text_update.restype = c_bool
_lib.TCOD_text_update.argtypes = [c_void_p, c_int]

_lib.TCOD_text_render.restype = c_void
_lib.TCOD_text_render.argtypes = [c_void_p, c_void_p]

_lib.TCOD_text_get.restype = c_char_p
_lib.TCOD_text_get.argtypes = [c_void_p]

_lib.TCOD_text_reset.restype = c_void
_lib.TCOD_text_reset.argtypes = [c_void_p]

_lib.TCOD_text_delete.restype = c_void
_lib.TCOD_text_delete.argtypes = [c_void_p]

_lib.TCOD_zip_new.restype = c_void_p
_lib.TCOD_zip_new.argtypes = []

_lib.TCOD_zip_delete.restype = c_void
_lib.TCOD_zip_delete.argtypes = [c_void_p]

_lib.TCOD_zip_put_char.restype = c_void
_lib.TCOD_zip_put_char.argtypes = [c_void_p, c_char]

_lib.TCOD_zip_put_int.restype = c_void
_lib.TCOD_zip_put_int.argtypes = [c_void_p, c_int]

_lib.TCOD_zip_put_float.restype = c_void
_lib.TCOD_zip_put_float.argtypes = [c_void_p, c_float]

_lib.TCOD_zip_put_string.restype = c_void
_lib.TCOD_zip_put_string.argtypes = [c_void_p, c_char_p]

_lib.TCOD_zip_put_color.restype = c_void
_lib.TCOD_zip_put_color.argtypes = [c_void_p, c_int]

_lib.TCOD_zip_put_image.restype = c_void
_lib.TCOD_zip_put_image.argtypes = [c_void_p, c_void_p]

_lib.TCOD_zip_put_console.restype = c_void
_lib.TCOD_zip_put_console.argtypes = [c_void_p, c_void_p]

_lib.TCOD_zip_put_data.restype = c_void
_lib.TCOD_zip_put_data.argtypes = [c_void_p, c_int, c_void_p]

_lib.TCOD_zip_get_current_bytes.restype = c_int
_lib.TCOD_zip_get_current_bytes.argtypes = [c_void_p]

_lib.TCOD_zip_save_to_file.restype = c_int
_lib.TCOD_zip_save_to_file.argtypes = [c_void_p, c_char_p]

_lib.TCOD_zip_load_from_file.restype = c_int
_lib.TCOD_zip_load_from_file.argtypes = [c_void_p, c_char_p]

_lib.TCOD_zip_get_char.restype = c_char
_lib.TCOD_zip_get_char.argtypes = [c_void_p]

_lib.TCOD_zip_get_int.restype = c_int
_lib.TCOD_zip_get_int.argtypes = [c_void_p]

_lib.TCOD_zip_get_float.restype = c_float
_lib.TCOD_zip_get_float.argtypes = [c_void_p]

_lib.TCOD_zip_get_string.restype = c_char_p
_lib.TCOD_zip_get_string.argtypes = [c_void_p]

_lib.TCOD_zip_get_color.restype = c_int
_lib.TCOD_zip_get_color.argtypes = [c_void_p]

_lib.TCOD_zip_get_image.restype = c_void_p
_lib.TCOD_zip_get_image.argtypes = [c_void_p]

_lib.TCOD_zip_get_console.restype = c_void_p
_lib.TCOD_zip_get_console.argtypes = [c_void_p]

_lib.TCOD_zip_get_data.restype = c_int
_lib.TCOD_zip_get_data.argtypes = [c_void_p, c_int, c_void_p]

_lib.TCOD_zip_get_remaining_bytes.restype = c_int
_lib.TCOD_zip_get_remaining_bytes.argtypes = [c_void_p]

_lib.TCOD_zip_skip_bytes.restype = c_void
_lib.TCOD_zip_skip_bytes.argtypes = [c_void_p, c_int]
