Noise.__copy__()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
"""
2
    This module provides advanced noise generation.
3
4
    Noise is sometimes used for over-world generation, height-maps, and
5
    cloud/mist/smoke effects among other things.
6
7
    You can see examples of the available noise algorithms in the libtcod
8
    documentation `here
9
    <http://doryen.eptalys.net/data/libtcod/doc/1.5.1/html2/noise.html>`_.
10
"""
11
12
13
import random as _random
14
15
from tcod import ffi as _ffi
16
from tcod import lib as _lib
17
18
import tdl as _tdl
19
from . import style as _style
20
21
_MERSENNE_TWISTER = 1
22
_CARRY_WITH_MULTIPLY = 2
23
24
_MAX_DIMENSIONS = 4
25
_MAX_OCTAVES = 128
26
27
_NOISE_TYPES = {'PERLIN': 1, 'SIMPLEX': 2, 'WAVELET': 4}
28
_NOISE_MODES = {'FLAT': _lib.TCOD_noise_get,
29
                'FBM': _lib.TCOD_noise_get_fbm,
30
                'TURBULENCE': _lib.TCOD_noise_get_turbulence}
31
32
class Noise(object):
33
    """An advanced noise generator.
34
35
    .. deprecated:: 3.2
36
        This class has been replaced by :any:`tcod.noise.Noise`.
37
38
    Args:
39
        algorithm (Text): The primary noise algorithm to be used.
40
41
            Can be one of 'PERLIN', 'SIMPLEX', 'WAVELET'
42
43
            - 'PERLIN' -
44
              A popular noise generator.
45
            - 'SIMPLEX' -
46
              In theory this is a slightly faster generator with
47
              less noticeable directional artifacts.
48
            - 'WAVELET' -
49
              A noise generator designed to reduce aliasing and
50
              not lose detail when summed into a fractal
51
              (as with the 'FBM' and 'TURBULENCE' modes.)
52
              This works faster at higher dimensions.
53
54
        mode (Text): A secondary parameter to determine how noise is generated.
55
56
            Can be one of 'FLAT', 'FBM', 'TURBULENCE'
57
58
            - 'FLAT' -
59
              Generates the simplest form of noise.
60
              This mode does not use the hurst, lacunarity,
61
              and octaves parameters.
62
            - 'FBM' -
63
              Generates fractal brownian motion.
64
            - 'TURBULENCE' -
65
              Generates detailed noise with smoother and more
66
              natural transitions.
67
68
        hurst (float): The hurst exponent.
69
70
            This describes the raggedness of the resultant noise,
71
            with a higher value leading to a smoother noise.
72
            It should be in the 0.0-1.0 range.
73
74
            This is only used in 'FBM' and 'TURBULENCE' modes.
75
76
        lacunarity (float): A multiplier that determines how quickly the
77
            frequency increases for each successive octave.
78
79
            The frequency of each successive octave is equal to
80
            the product of the previous octave's frequency and
81
            the lacunarity value.
82
83
            This is only used in 'FBM' and 'TURBULENCE' modes.
84
85
        octaves (float): Controls the amount of detail in the noise.
86
87
            This is only used in 'FBM' and 'TURBULENCE' modes.
88
89
        seed (Hashable): You can use any hashable object to be a seed for the
90
            noise generator.
91
92
            If None is used then a random seed will be generated.
93
    """
94
95
    def __init__(self, algorithm='PERLIN', mode='FLAT',
96
                 hurst=0.5, lacunarity=2.0, octaves=4.0, seed=None, dimensions=4):
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
97
        if algorithm.upper() not in _NOISE_TYPES:
98
            raise _tdl.TDLError('No such noise algorithm as %s' % algorithm)
99
        self._algorithm = algorithm.upper()
100
101
        if mode.upper() not in _NOISE_MODES:
102
            raise _tdl.TDLError('No such mode as %s' % mode)
103
        self._mode = mode.upper()
104
105
        if seed is None:
106
            seed = _random.getrandbits(32)
107
        try:
108
            seed = int(seed)
109
        except TypeError:
110
            seed = hash(seed)
111
        self._seed = seed
112
        # convert values into ctypes to speed up later functions
113
        self._dimensions = min(_MAX_DIMENSIONS, int(dimensions))
114
        if self._algorithm == 'WAVELET':
115
            self._dimensions = min(self._dimensions, 3) # Wavelet only goes up to 3
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (83/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
116
        self._random = _lib.TCOD_random_new_from_seed(
117
            _MERSENNE_TWISTER,
118
            _ffi.cast('uint32_t', self._seed),
119
            )
120
        self._hurst = hurst
121
        self._lacunarity = lacunarity
122
        self._noise = _lib.TCOD_noise_new(self._dimensions, self._hurst,
123
                                          self._lacunarity, self._random)
124
        _lib.TCOD_noise_set_type(self._noise, _NOISE_TYPES[self._algorithm])
125
        self._noiseFunc = _NOISE_MODES[self._mode]
0 ignored issues
show
Coding Style Naming introduced by
The name _noiseFunc 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...
126
        self._octaves = octaves
127
        self._useOctaves = (self._mode != 'FLAT')
0 ignored issues
show
Coding Style Naming introduced by
The name _useOctaves 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...
128
        self._arrayType = 'float[%i]' % self._dimensions
0 ignored issues
show
Coding Style Naming introduced by
The name _arrayType 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...
129
        #self._cFloatArray = _ctypes.c_float * self._dimensions
130
        #self._array = self._cFloatArray()
131
132
    def __copy__(self):
133
        # using the pickle method is a convenient way to clone this object
134
        return self.__class__(*self.__getstate__())
135
136
    def __getstate__(self):
137
        return (self._algorithm, self._mode,
138
                self._hurst, self._lacunarity, self._octaves,
139
                self._seed, self._dimensions)
140
141
    def __setstate__(self, state):
142
        self.__init__(*state)
143
144
    def get_point(self, *position):
145
        """Return the noise value of a specific position.
146
147
        Example usage: value = noise.getPoint(x, y, z)
148
149
        Args:
150
            position (Tuple[float, ...]): The point to sample at.
151
152
        Returns:
153
            float: The noise value at position.
154
155
                This will be a floating point in the 0.0-1.0 range.
156
        """
157
        #array = self._array
158
        #for d, pos in enumerate(position):
159
        #    array[d] = pos
160
        #array = self._cFloatArray(*position)
161
        array = _ffi.new(self._arrayType, position)
162
        if self._useOctaves:
163
            return (self._noiseFunc(self._noise, array, self._octaves) + 1) * 0.5
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (81/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
164
        return (self._noiseFunc(self._noise, array) + 1) * 0.5
165
166
167
__all__ = [_var for _var in locals().keys() if _var[0] != '_']
168
169
Noise.getPoint = _style.backport(Noise.get_point)
170