HexDecimal /
python-tdl
| 1 | ''' |
||
| 2 | The following example shows how to travrse the BSP tree using Python. This |
||
| 3 | assumes `create_room` and `connect_rooms` will be replaced by custom code. |
||
| 4 | |||
| 5 | Example:: |
||
| 6 | |||
| 7 | import tcod.bsp |
||
| 8 | |||
| 9 | def create_room(node): |
||
| 10 | """Initialize the room at this current node.""" |
||
| 11 | print('Create a room for %s.' % node) |
||
| 12 | |||
| 13 | def connect_rooms(node): |
||
| 14 | """Connect two fully initialized rooms.""" |
||
| 15 | node1, node2 = node.children |
||
| 16 | print('Connect the rooms:\\n%s\\n%s' % (node1, node2)) |
||
| 17 | |||
| 18 | def traverse(node): |
||
| 19 | """Traverse a BSP tree dispatching nodes to the correct calls.""" |
||
| 20 | # For nodes without children, node.children is an empty tuple. |
||
| 21 | for child in node.children: |
||
| 22 | traverse(child) |
||
| 23 | |||
| 24 | if node.children: |
||
| 25 | connect_rooms(node) |
||
| 26 | else: |
||
| 27 | create_room(node) |
||
| 28 | |||
| 29 | bsp = tcod.bsp.BSP(x=0, y=0, width=80, height=60) |
||
| 30 | bsp.split_recursive( |
||
| 31 | depth=5, |
||
| 32 | min_width=3, |
||
| 33 | min_height=3, |
||
| 34 | max_horizontal_ratio=1.5, |
||
| 35 | max_vertical_ratio=1.5, |
||
| 36 | ) |
||
| 37 | traverse(bsp) |
||
| 38 | ''' |
||
| 39 | from __future__ import absolute_import as _ |
||
| 40 | |||
| 41 | from tcod.libtcod import lib, ffi |
||
| 42 | |||
| 43 | |||
| 44 | class BSP(object): |
||
| 45 | """A binary space partitioning tree which can be used for simple dungeon |
||
| 46 | generation. |
||
| 47 | |||
| 48 | Attributes: |
||
| 49 | x (int): Rectangle left coordinate. |
||
| 50 | y (int): Rectangle top coordinate. |
||
| 51 | width (int): Rectangle width. |
||
| 52 | height (int): Rectangle height. |
||
| 53 | level (int): This nodes depth. |
||
| 54 | position (int): The integer of where the node was split. |
||
| 55 | horizontal (bool): This nodes split orientation. |
||
| 56 | parent (Optional[BSP]): This nodes parent or None |
||
| 57 | children (Optional[Tuple[BSP, BSP]]): |
||
| 58 | A tuple of (left, right) BSP instances, or |
||
| 59 | None if this BSP has no children. |
||
| 60 | |||
| 61 | Args: |
||
| 62 | x (int): Rectangle left coordinate. |
||
| 63 | y (int): Rectangle top coordinate. |
||
| 64 | width (int): Rectangle width. |
||
| 65 | height (int): Rectangle height. |
||
| 66 | """ |
||
| 67 | |||
| 68 | def __init__(self, x, y, width, height): |
||
| 69 | self.x = x |
||
|
0 ignored issues
–
show
|
|||
| 70 | self.y = y |
||
|
0 ignored issues
–
show
The name
y does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
|
|||
| 71 | self.width = width |
||
| 72 | self.height = height |
||
| 73 | |||
| 74 | self.level = 0 |
||
| 75 | self.position = 0 |
||
| 76 | self.horizontal = False |
||
| 77 | |||
| 78 | self.parent = None |
||
| 79 | self.children = () |
||
| 80 | |||
| 81 | @property |
||
| 82 | def w(self): |
||
|
0 ignored issues
–
show
The name
w does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 83 | return self.width |
||
| 84 | @w.setter |
||
| 85 | def w(self, value): |
||
|
0 ignored issues
–
show
The name
w does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 86 | self.width = value |
||
| 87 | |||
| 88 | @property |
||
| 89 | def h(self): |
||
|
0 ignored issues
–
show
The name
h does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 90 | return self.height |
||
| 91 | @h.setter |
||
| 92 | def h(self, value): |
||
|
0 ignored issues
–
show
The name
h does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 93 | self.height = value |
||
| 94 | |||
| 95 | def _as_cdata(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 96 | cdata = ffi.gc(lib.TCOD_bsp_new_with_size(self.x, self.y, |
||
| 97 | self.width, self.height), |
||
| 98 | lib.TCOD_bsp_delete) |
||
| 99 | cdata.level = self.level |
||
| 100 | return cdata |
||
| 101 | |||
| 102 | def __str__(self): |
||
| 103 | """Provide a useful readout when printed.""" |
||
| 104 | status = 'leaf' |
||
| 105 | if self.children: |
||
| 106 | status = ('split at position=%i,horizontal=%r' % |
||
| 107 | (self.position, self.horizontal)) |
||
| 108 | |||
| 109 | return ('<%s(x=%i,y=%i,width=%i,height=%i)level=%i,%s>' % |
||
| 110 | (self.__class__.__name__, |
||
| 111 | self.x, self.y, self.width, self.height, self.level, status)) |
||
| 112 | |||
| 113 | def _unpack_bsp_tree(self, cdata): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 114 | self.x = cdata.x |
||
| 115 | self.y = cdata.y |
||
| 116 | self.width = cdata.w |
||
| 117 | self.height = cdata.h |
||
| 118 | self.level = cdata.level |
||
| 119 | self.position = cdata.position |
||
| 120 | self.horizontal = bool(cdata.horizontal) |
||
| 121 | if lib.TCOD_bsp_is_leaf(cdata): |
||
| 122 | return |
||
| 123 | self.children = (BSP(0, 0, 0, 0), BSP(0, 0, 0, 0)) |
||
| 124 | self.children[0].parent = self |
||
| 125 | self.children[0]._unpack_bsp_tree(lib.TCOD_bsp_left(cdata)) |
||
| 126 | self.children[1].parent = self |
||
| 127 | self.children[1]._unpack_bsp_tree(lib.TCOD_bsp_right(cdata)) |
||
| 128 | |||
| 129 | def split_once(self, horizontal, position): |
||
| 130 | """Split this partition into 2 sub-partitions. |
||
| 131 | |||
| 132 | Args: |
||
| 133 | horizontal (bool): |
||
| 134 | position (int): |
||
| 135 | """ |
||
| 136 | cdata = self._as_cdata() |
||
| 137 | lib.TCOD_bsp_split_once(cdata, horizontal, position) |
||
| 138 | self._unpack_bsp_tree(cdata) |
||
| 139 | |||
| 140 | def split_recursive(self, depth, min_width, min_height, |
||
| 141 | max_horizontal_ratio, max_vertical_ratio, seed=None): |
||
| 142 | """Divide this partition recursively. |
||
| 143 | |||
| 144 | Args: |
||
| 145 | depth (int): The maximum depth to divide this object recursively. |
||
| 146 | min_width (int): The minimum width of any individual partition. |
||
| 147 | min_height (int): The minimum height of any individual partition. |
||
| 148 | max_horizontal_ratio (float): |
||
| 149 | Prevent creating a horizontal ratio more extreme than this. |
||
| 150 | max_vertical_ratio (float): |
||
| 151 | Prevent creating a vertical ratio more extreme than this. |
||
| 152 | seed (Optional[tcod.random.Random]): |
||
| 153 | The random number generator to use. |
||
| 154 | """ |
||
| 155 | cdata = self._as_cdata() |
||
| 156 | lib.TCOD_bsp_split_recursive( |
||
| 157 | cdata, |
||
| 158 | seed or ffi.NULL, |
||
| 159 | depth, |
||
| 160 | min_width, min_height, |
||
| 161 | max_horizontal_ratio, max_vertical_ratio, |
||
| 162 | ) |
||
| 163 | self._unpack_bsp_tree(cdata) |
||
| 164 | |||
| 165 | def walk(self): |
||
| 166 | """Iterate over this BSP's hieracrhy. |
||
| 167 | |||
| 168 | The iterator will include the instance which called it. |
||
| 169 | It will traverse its own children and grandchildren, in no particular |
||
| 170 | order. |
||
| 171 | |||
| 172 | Returns: |
||
| 173 | Iterator[BSP]: An iterator of BSP nodes. |
||
| 174 | |||
| 175 | .. deprecated:: 2.3 |
||
| 176 | See the module example for how to iterate over a BSP tree. |
||
| 177 | """ |
||
| 178 | return self._iter_post_order() |
||
| 179 | |||
| 180 | def _iter_pre_order(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 181 | yield self |
||
| 182 | for child in self.children: |
||
| 183 | for grandchild in child._iter_pre_order(): |
||
| 184 | yield grandchild |
||
| 185 | |||
| 186 | def _iter_in_order(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 187 | if self.children: |
||
| 188 | for grandchild in self.children[0]._iter_in_order(): |
||
| 189 | yield grandchild |
||
| 190 | yield self |
||
| 191 | for grandchild in self.children[1]._iter_in_order(): |
||
| 192 | yield grandchild |
||
| 193 | else: |
||
| 194 | yield self |
||
| 195 | |||
| 196 | def _iter_post_order(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 197 | for child in self.children: |
||
| 198 | for grandchild in child._iter_post_order(): |
||
| 199 | yield grandchild |
||
| 200 | yield self |
||
| 201 | |||
| 202 | def _iter_level_order(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 203 | return sorted(self._iter_pre_order(), key=lambda n:n.level) |
||
|
0 ignored issues
–
show
|
|||
| 204 | |||
| 205 | def _iter_inverted_level_order(self): |
||
|
0 ignored issues
–
show
This method should have a docstring.
The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods: class SomeClass:
def some_method(self):
"""Do x and return foo."""
If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions. Loading history...
|
|||
| 206 | return reversed(self._iter_level_order()) |
||
| 207 | |||
| 208 | def contains(self, x, y): |
||
|
0 ignored issues
–
show
The name
x does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
The name
y does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
|
|||
| 209 | """Returns True if this node contains these coordinates. |
||
| 210 | |||
| 211 | Args: |
||
| 212 | x (int): X position to check. |
||
| 213 | y (int): Y position to check. |
||
| 214 | |||
| 215 | Returns: |
||
| 216 | bool: True if this node contains these coordinates. |
||
| 217 | Otherwise False. |
||
| 218 | """ |
||
| 219 | return (self.x <= x < self.x + self.width and |
||
| 220 | self.y <= y < self.y + self.height) |
||
| 221 | |||
| 222 | def find_node(self, x, y): |
||
|
0 ignored issues
–
show
The name
x does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
The name
y does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).
This check looks for invalid names for a range of different identifiers. You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements. If your project includes a Pylint configuration file, the settings contained in that file take precedence. To find out more about Pylint, please refer to their site. Loading history...
|
|||
| 223 | """Return the deepest node which contains these coordinates. |
||
| 224 | |||
| 225 | Returns: |
||
| 226 | Optional[BSP]: BSP object or None. |
||
| 227 | """ |
||
| 228 | if not self.contains(x, y): |
||
| 229 | return None |
||
| 230 | for child in self.children: |
||
| 231 | found = child.find_node(x, y) |
||
| 232 | if found: |
||
| 233 | return found |
||
| 234 | return self |
||
| 235 |
This check looks for invalid names for a range of different identifiers.
You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.
If your project includes a Pylint configuration file, the settings contained in that file take precedence.
To find out more about Pylint, please refer to their site.