devpace 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
devPace/main.py ADDED
@@ -0,0 +1,184 @@
1
+ import pygame
2
+ import sys
3
+ import os
4
+ import multiprocessing
5
+ from ._net import Global, _global_
6
+ from .basics.input import Keys
7
+ from .physics.collisions import CollisionRect
8
+ from .assets.cache import Assets
9
+
10
+ from .GlobalDebugger import GlobalDebugger
11
+
12
+
13
+ MIN_LAYER = -5
14
+ MAX_LAYER = 10
15
+ ALL_COLLISION_LAYERS = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
16
+
17
+ class Engine:
18
+ def __init__(self, bg="black", title="Pygame Win", width=800, height=600, EXPERIMENTAL_RESIZABLE=False, TARGET_FPS=60, EXPERIMENTAL_DEBUG=False):
19
+ if EXPERIMENTAL_RESIZABLE: self._display = pygame.display.set_mode((width, height), flags=pygame.RESIZABLE)
20
+ else: self._display = pygame.display.set_mode((width, height))
21
+ pygame.display.set_caption(title)
22
+
23
+ if EXPERIMENTAL_DEBUG:
24
+ print("Starting GlobalDebugger...")
25
+ self.log_queue = multiprocessing.Queue()
26
+ self.debug_prossess = multiprocessing.Process(target=GlobalDebugger, args=(self.log_queue,)).start()
27
+
28
+
29
+ self.screen_dim = (width, height)
30
+ self.width = width
31
+ self.height = height
32
+ self.RESIZABLE = EXPERIMENTAL_RESIZABLE
33
+
34
+ self.screen = pygame.surface.Surface((width, height))
35
+ self.bg = bg
36
+ self.title = title
37
+
38
+ self.clock = pygame.time.Clock()
39
+ self.FPS = TARGET_FPS
40
+
41
+ #update global
42
+ Global.display = self._display
43
+ Global.screen = self.screen
44
+ Global.bg = self.bg
45
+ Global.title = self.title
46
+ Global.clock = self.clock
47
+ Global.assets = Assets
48
+ Global.all_collision_layers = ALL_COLLISION_LAYERS
49
+
50
+ def Tick(self):
51
+ self.update()
52
+ self.render()
53
+
54
+ def update(self):
55
+ #dt
56
+ Global.dt = self.clock.tick(self.FPS) / 1000.0
57
+ #events
58
+ Global.events = pygame.event.get()
59
+ for event in Global.events:
60
+ if event.type == pygame.QUIT:
61
+ self.exit()
62
+ if event.type == pygame.VIDEORESIZE and self.RESIZABLE:
63
+ self._auto_resize(event)
64
+ #updates
65
+
66
+ #keys
67
+ Keys.update()
68
+
69
+ #cam
70
+ Global.cam.update()
71
+ #objects
72
+ layer=MIN_LAYER
73
+ while layer<=MAX_LAYER:
74
+ if layer in Global.objects:
75
+ i = Global.objects[layer]
76
+ for obj in i:
77
+ try:
78
+ obj.update()
79
+ except AttributeError:
80
+ pass
81
+ layer+=1
82
+
83
+
84
+ def render(self):
85
+ self.screen.fill(self.bg)
86
+ #render to screen
87
+ layer=MIN_LAYER
88
+ while layer<=MAX_LAYER:
89
+ if layer in Global.objects:
90
+ i = Global.objects[layer]
91
+ for obj in i:
92
+ try:
93
+ obj.render()
94
+ except AttributeError:
95
+ pass
96
+ layer+=1
97
+
98
+
99
+ #update screen(display)
100
+ self._display.fill(self.bg)
101
+ self._display.blit(pygame.transform.scale(self.screen, self.screen_dim), (0, 0))
102
+ pygame.display.flip()
103
+
104
+ def exit(self):
105
+ os.system("cls")
106
+ pygame.quit()
107
+ sys.exit()
108
+
109
+ def _auto_resize(self, event):
110
+ w, h = event.size
111
+ self._display = pygame.display.set_mode((w, h), flags=pygame.RESIZABLE)
112
+ self.screen_dim = (w, h)
113
+ Global.FW = w / self.screen_dim[0]
114
+ Global.FH = h / self.screen_dim[1]
115
+ def all_colision_layers(self):
116
+ return ALL_COLLISION_LAYERS
117
+
118
+ def manual_resize(self, width, height):
119
+ self._display = pygame.display.set_mode((width, height), flags=pygame.RESIZABLE)
120
+ self.screen_dim = (width, height)
121
+ Global.FW = width / self.screen_dim[0]
122
+ Global.FH = height / self.screen_dim[1]
123
+
124
+ def create_aroundScreen_bounds(self):
125
+ CollisionRect(0, -5, self.screen_dim[0], 5, ALL_COLLISION_LAYERS)
126
+ CollisionRect(-5, 0, 5, self.screen_dim[1], ALL_COLLISION_LAYERS)
127
+ CollisionRect(self.screen_dim[0], 0, 5, self.screen_dim[1], ALL_COLLISION_LAYERS)
128
+ CollisionRect(0, self.screen_dim[1], self.screen_dim[0], 5, ALL_COLLISION_LAYERS)
129
+
130
+ def _func_get_global_(self) -> _global_:
131
+ print("<Engine> Global accsesed")
132
+ return Global
133
+
134
+ def get_current_fps(self):
135
+ return self.clock.get_fps()
136
+
137
+ def change_title(self, title):
138
+ Global.title = title
139
+ pygame.display.set_caption(title)
140
+ self.title = title
141
+
142
+ #scene logic
143
+ def new_scene(self, name, scene):
144
+ Global.scenes[name] = scene
145
+ def change_scene(self, name, resetCam=True, resetObjects=True):
146
+ if resetCam: Global.cam = None
147
+ if resetObjects:
148
+ Global.tilemaps = {}
149
+ Global.objects = {}
150
+ if name in Global.scenes:
151
+ if Global.current_scene is not None:
152
+ Global.last_scene = Global.current_scene
153
+ Global.current_scene.on_end()
154
+ Global.current_scene = Global.scenes[name]
155
+ Global.current_scene.on_end()
156
+ Global.current_scene.on_start()
157
+ Global.current_scene.run()
158
+
159
+ def reload_scene(self, resetCam=True, resetObjects=True, end=True, start=True):
160
+ if Global.current_scene is not None:
161
+ if resetCam:
162
+ Global.tilemaps = {}
163
+ Global.cam = None
164
+ if resetObjects: Global.objects = {}
165
+ if end: Global.current_scene.on_end()
166
+ if start: Global.current_scene.on_start()
167
+ Global.current_scene.run()
168
+
169
+ def back_scene(self):
170
+ if Global.last_scene is not None:
171
+ self.change_scene(Global.last_scene)
172
+
173
+ def remove_scene(self, name):
174
+ if name in Global.scenes:
175
+ del Global.scenes[name]
176
+ class Scene:
177
+ def __init__(self):
178
+ pass
179
+ def run(self):
180
+ pass
181
+ def on_start(self):
182
+ pass
183
+ def on_end(self):
184
+ pass
@@ -0,0 +1,87 @@
1
+ import pygame
2
+
3
+ from .._net import Global
4
+
5
+
6
+ import pygame
7
+ from .._net import Global
8
+ from ..helpers.utils import change_layer
9
+ from .collisions import CollisionRect
10
+ class KinematicPlatform:
11
+ def __init__(self, x, y, width, height, speed, show=True, layer=3, waypoints=[], loop=True, snapDist = 5):
12
+ self.x = x
13
+ self.y = y
14
+ self.vx = 0.0
15
+ self.vy = 0.0
16
+ self.width = width
17
+ self.height = height
18
+ self.show = show
19
+ self.layer = layer
20
+
21
+ self.waypoints = waypoints
22
+ self.currentWaypoint = 0
23
+ self.speed = speed
24
+ self.loop = loop
25
+ self.snapDist = snapDist
26
+
27
+ self.collision = CollisionRect(x, y, width, height)
28
+ self.collision.layers = [layer]
29
+
30
+ Global.add_object(layer, self)
31
+
32
+ self.shape = None
33
+ self.image = None
34
+ self.animation = None
35
+ self.animationManager = None
36
+
37
+ def change_layer(self, new_layer):
38
+ change_layer(self, new_layer, self.layer)
39
+ self.layer = new_layer
40
+
41
+ def update(self):
42
+ self.vx = 0.0
43
+ self.vy = 0.0
44
+ #move toward current waypoint
45
+ if self.currentWaypoint < len(self.waypoints):
46
+ if self.x > self.waypoints[self.currentWaypoint][0]:
47
+ self.vx = -self.speed
48
+ elif self.x < self.waypoints[self.currentWaypoint][0]:
49
+ self.vx = self.speed
50
+ if self.y > self.waypoints[self.currentWaypoint][1]:
51
+ self.vy = -self.speed
52
+ elif self.y < self.waypoints[self.currentWaypoint][1]:
53
+ self.vy = self.speed
54
+
55
+ #if at waypoint,or snapdist, move to next waypoint
56
+ if abs(self.x - self.waypoints[self.currentWaypoint][0]) < self.snapDist and abs(self.y - self.waypoints[self.currentWaypoint][1]) < self.snapDist:
57
+ self.currentWaypoint+=1
58
+ if self.currentWaypoint >= len(self.waypoints):
59
+ if self.loop:
60
+ self.currentWaypoint = 0
61
+
62
+
63
+
64
+ #x movement
65
+ self.x+=self.vx*Global.dt
66
+ self.collision.x = self.x
67
+ self.y+=self.vy*Global.dt
68
+ self.collision.y = self.y
69
+
70
+ #update any other positions now
71
+ if self.shape is not None:
72
+ self.shape.x = self.x
73
+ self.shape.y = self.y
74
+
75
+ if self.image is not None:
76
+ self.image.x = self.x
77
+ self.image.y = self.y
78
+
79
+ if self.animation is not None:
80
+ self.animation.x = self.x
81
+ self.animation.y = self.y
82
+
83
+ if self.animationManager is not None:
84
+ self.animationManager.x = self.x
85
+ self.animationManager.y = self.y
86
+
87
+
@@ -0,0 +1,87 @@
1
+ import pygame
2
+
3
+ from .._net import Global
4
+ from ..assets.animations import AnimationManager
5
+
6
+ class _constraints_:
7
+ def __init__(self):
8
+ #define dir <>^_#o
9
+ self.dir_up = 'V^'
10
+ self.dir_down = 'Vv'
11
+ self.dir_left = 'V<'
12
+ self.dir_right = 'V>'
13
+ self.dir_any = 'V#'
14
+ self.dir_none = 'Vo'
15
+
16
+ Constraints = _constraints_()
17
+
18
+ class AutoStateManager:
19
+ def __init__(self, manager: AnimationManager = None, obj=None):
20
+ Global.add_object(1, self)
21
+ self.manager = manager
22
+ self.state = None
23
+ self.states: dict[list[str], str] = {}
24
+ self.weights: dict[str, int] = {}
25
+ self.obj = obj
26
+
27
+ def set_obj(self, obj):
28
+ self.obj = obj
29
+
30
+ def add_state(self, constraints: list[str], state: str, weight=0):
31
+ self.states[tuple(constraints)] = state
32
+ self.weights[state] = weight
33
+ def remove_state(self, state: str):
34
+ self.states.remove(state)
35
+ def set_state(self, name):
36
+ self.current_state = name
37
+ if self.manager is not None and name in self.manager.animations:
38
+ self.manager.play_animation(name)
39
+
40
+ def update(self):
41
+ if self.obj is None: return
42
+ if self.manager is None: return
43
+ #eval all states and pick wining num
44
+ states: dict[str, int] ={}
45
+ for constraints, state in self.states.items():
46
+ #velocity tests
47
+ states = self._eval_velocity(constraints, state, states)
48
+ states[state] += self.weights[state]
49
+ #pick the highest state
50
+ self.state = max(states, key=states.get)
51
+ if self.manager is not None and self.state in self.manager.animations:
52
+ self.manager.play_animation(self.state)
53
+
54
+
55
+ def _eval_velocity(self, conditions, state, _end):
56
+ if len(conditions) == 0: _end[state] += 0
57
+ #up, down, left, right, all, none
58
+ if not hasattr(self.obj, 'vx') and hasattr(self.obj, 'vy'): return _end
59
+ #else do checks
60
+ if 'V^' in conditions and self.obj.vy < 0: _end[state] += 1
61
+ if 'Vv' in conditions and self.obj.vy > 0: _end[state] += 1
62
+ if 'V<' in conditions and self.obj.vx < 0: _end[state] += 1
63
+ if 'V>' in conditions and self.obj.vx > 0: _end[state] += 1
64
+ if 'V#' in conditions and self.obj.vx != 0 and self.obj.vy != 0: _end[state] += 1
65
+ if 'Vo' in conditions and self.obj.vx == 0 and self.obj.vy == 0: _end[state] += 1
66
+ return _end
67
+
68
+
69
+ class StateManager:
70
+ def __init__(self, manager: AnimationManager = None, states=[]):
71
+ #Global.add_object(1, self)
72
+ self.manager = manager
73
+ self.state = None
74
+ self.states: list[str] = states
75
+
76
+ def add_state(self, constraints: list[str], state: str):
77
+ if state not in self.states:
78
+ self.states.append(state)
79
+
80
+ def remove_state(self, state):
81
+ if state in self.states:
82
+ self.states.remove(state)
83
+
84
+ def set_state(self, name):
85
+ self.current_state = name
86
+ if self.manager is not None and name in self.manager.animations:
87
+ self.manager.play_animation(name)
@@ -0,0 +1,40 @@
1
+ import pygame
2
+ import random
3
+ from .._net import Global
4
+
5
+
6
+ class CollisionRect:
7
+ def __init__(self, x, y, width, height, layers=[]):
8
+ self.x, self.y, self.width, self.height = x, y, width, height
9
+ self.layers = layers
10
+ Global.collisions.append(self)
11
+ self.active = True
12
+
13
+ self.color = (random.randint(0, 255), 0, random.randint(0, 255))
14
+
15
+ def rect(self):
16
+ return pygame.Rect(self.x, self.y, self.width, self.height)
17
+
18
+ def Del(self):
19
+ if self not in Global.collisions: return
20
+ Global.collisions.remove(self)
21
+
22
+ def isColliding(self):
23
+ if not self.active: return False
24
+ for obj in Global.collisions:
25
+ if obj == self: continue
26
+ for layer in self.layers:
27
+ if layer in obj.layers:
28
+ if obj.rect().colliderect(self.rect()):
29
+ return True
30
+
31
+ return False
32
+
33
+ def copy(self):
34
+ return CollisionRect(self.x, self.y, self.width, self.height, self.layers)
35
+
36
+ def render(self):
37
+ rect = self.rect()
38
+ rect.x = self.x-Global.cam.x
39
+ rect.y = self.y-Global.cam.y
40
+ pygame.draw.rect(Global.screen, self.color, rect)
@@ -0,0 +1,135 @@
1
+ import pygame
2
+ from .._net import Global
3
+ from ..helpers.utils import change_layer
4
+ from .collisions import CollisionRect
5
+ class DynamicBody:
6
+ def __init__(self, x, y, width, height, vx=0.0, vy=0.0, show=True, layer=3, gravity=0.0, smartCollisions=True, smartCollisionDist=1):
7
+ self.x = x
8
+ self.y = y
9
+ self.vx = vx
10
+ self.vy = vy
11
+ self.width = width
12
+ self.height = height
13
+ self.show = show
14
+ self.layer = layer
15
+ self.gravity = gravity
16
+
17
+ self.collision = CollisionRect(x, y, width, height)
18
+ self.collision.layers = [layer]
19
+
20
+ Global.add_object(layer, self)
21
+
22
+ self.shape = None
23
+ self.image = None
24
+ self.animation = None
25
+ self.animationManager = None
26
+
27
+ #collision checks
28
+ self.smartCollisions = smartCollisions
29
+ self.smartCollisionDist = smartCollisionDist
30
+
31
+ self.is_on_floor = False
32
+ self.is_on_ceiling = False
33
+ self.is_on_left = False
34
+ self.is_on_right = False
35
+ self.is_on_wall = False
36
+
37
+
38
+ def change_layer(self, new_layer):
39
+ change_layer(self, new_layer, self.layer)
40
+ self.layer = new_layer
41
+
42
+
43
+ def update(self):
44
+
45
+ #collision checks
46
+ self.is_on_floor = False
47
+ self.is_on_ceiling = False
48
+ self.is_on_left = False
49
+ self.is_on_right = False
50
+ self.is_on_wall = False
51
+
52
+ #x movement
53
+ self.x+=self.vx*Global.dt
54
+ #if collisions, back up
55
+ self.collision.x = self.x
56
+ if self.collision.isColliding():
57
+ self.x-=self.vx*Global.dt
58
+ #colisions info
59
+ self.is_on_wall = True
60
+ if self.vx > 0.0:
61
+ self.is_on_right = True
62
+ elif self.vx < 0.0:
63
+ self.is_on_left = True
64
+ self.vx = 0
65
+
66
+ if self.smartCollisions:
67
+ if not self.is_on_left:
68
+ self.collision.x = self.x - self.smartCollisionDist
69
+ if self.collision.isColliding():
70
+ self.is_on_left = True
71
+ self.vx = 0.0
72
+ self.collision.x = self.x
73
+
74
+ if not self.is_on_right:
75
+ self.collision.x = self.x + self.smartCollisionDist
76
+ if self.collision.isColliding():
77
+ self.is_on_right = True
78
+ self.vx = 0.0
79
+ self.collision.x = self.x
80
+
81
+ #y movement
82
+ self.y += self.vy*Global.dt
83
+ #if collisions, back up
84
+ self.collision.y = self.y
85
+ if self.collision.isColliding():
86
+ self.y-=self.vy*Global.dt
87
+
88
+ #collision info
89
+ if self.vy > 0.0:
90
+ self.is_on_floor = True
91
+ if self.vy < 0.0:
92
+ self.is_on_ceiling = True
93
+
94
+ self.vy = 0
95
+
96
+ if self.smartCollisions:
97
+ if not self.is_on_floor:
98
+ self.collision.y = self.y + self.smartCollisionDist
99
+ if self.collision.isColliding():
100
+ self.is_on_floor = True
101
+ self.vy = 0.0
102
+ self.collision.y = self.y
103
+
104
+ if not self.is_on_ceiling:
105
+ self.collision.y = self.y - self.smartCollisionDist
106
+ if self.collision.isColliding():
107
+ self.is_on_ceiling = True
108
+ self.vy = 0.0
109
+ self.collision.y = self.y
110
+
111
+ #gravity
112
+ if not self.is_on_floor:
113
+ self.vy += self.gravity*Global.dt
114
+
115
+
116
+ self.collision.x = self.x
117
+ self.collision.y = self.y
118
+
119
+ #update any other positions now
120
+ if self.shape is not None:
121
+ self.shape.x = self.x
122
+ self.shape.y = self.y
123
+
124
+ if self.image is not None:
125
+ self.image.x = self.x
126
+ self.image.y = self.y
127
+
128
+ if self.animation is not None:
129
+ self.animation.x = self.x
130
+ self.animation.y = self.y
131
+
132
+ if self.animationManager is not None:
133
+ self.animationManager.x = self.x
134
+ self.animationManager.y = self.y
135
+
devPace/tracker.txt ADDED
@@ -0,0 +1,13 @@
1
+ This file is for tracking progress on certain parts of the project
2
+
3
+ TILEMAP:
4
+ v1
5
+ basic tiles laoding and saving with simple rendering
6
+
7
+ TILEMAP EDITOR:
8
+ v1
9
+ opens window for placing and removing tiles, with arrow key tile switching
10
+
11
+ TILEMAP COLLISION GEN:
12
+ v1
13
+ Generates seperate collisionRects for each tile.
Binary file
@@ -0,0 +1,24 @@
1
+ devPace/GlobalDebugger.py,sha256=hU1XRDzDyJkpQJ_irfIodb8Rl2ZrGX8nggZJo69_4hQ,1885
2
+ devPace/__init__.py,sha256=QDMjEYV2vTbQqNVSD2jVoH1QLELX1lUMH2ySNseiwao,918
3
+ devPace/_net.py,sha256=XnYRxk6FQVPlHnWVWy6EMzB0Vm8H852dCsFol0CH0UM,1417
4
+ devPace/main.py,sha256=5ztNSXlIbYVKmssCdOXmZo0W8eTvwnnR9fXJ_87Ke5U,6107
5
+ devPace/tracker.txt,sha256=Rniz3J4YQqW_qXGxXixbgegvW9sN1GQEPdDebFbqZu0,341
6
+ devPace/assets/animations.py,sha256=BqngXzJ2r0Ibx9GwyVY_7vFOExmR1J8LB3ONIx0XsRY,3840
7
+ devPace/assets/cache.py,sha256=6gATAWKBiQN5okCmqkXVdLiAGqttHZa_V-HvZXDuMPo,3355
8
+ devPace/assets/images.py,sha256=sCCl0v6O5wkr-8KVyh788RrPN54kC0R1EmuDsqZj49U,1655
9
+ devPace/assets/text.py,sha256=NH8oLzgRNn5iF_MBQ-KpFiO_9z6iNDrr8Adcm4VmrVg,202
10
+ devPace/assets/tilemap.py,sha256=eYONRe7UWAPDL99_FtWVXd-_ATfVJHJiw88kYVWHfrU,3247
11
+ devPace/basics/camera.py,sha256=Gn8dPm4JkcCBcquFDOCEzG_J0QqMAS7Bd10pg5bHZLM,887
12
+ devPace/basics/input.py,sha256=9CjiSkVL7qLEkYq9Q5fuNK2sMPhYtEH2NZKG3Z9vWOk,4121
13
+ devPace/basics/shapes.py,sha256=C0aaw7I8MhNtWDv5RqHFu1mDZpR9Dy_kY_-T8FR8-UM,2512
14
+ devPace/helpers/_tilemapEditor.py,sha256=zXCggIKnQjGyLndk37-2PCWrQOgh2BJhYBO2OiDQhdY,15041
15
+ devPace/helpers/_tilemap_files.py,sha256=tvWhIXUX5lytX7aDoJo-qQVYxL-JX9ZcN9ILooJX1Sg,6458
16
+ devPace/helpers/utils.py,sha256=ugli4wZxy2QW9R4c2amR2t2pym1h3YyA1AGJgAernu8,265
17
+ devPace/physics/KinematicPlatform.py,sha256=Ioo5pYekJvWH_BSRTz2uqj73zCuDeAk2sDP5pQFwFvA,2770
18
+ devPace/physics/StateManager.py,sha256=NmVApPmGKCVrB63M4apYni_gWYQ6Rf4fqg2no-VS_uc,3201
19
+ devPace/physics/collisions.py,sha256=ysAnUQ_Ks2eBsxHwWFNjZ3_7cqEKv09DXKbiAW-ukc4,1255
20
+ devPace/physics/dynamicBody.py,sha256=_HZCbAWW0M-2paU0xeDQofgQbXWl4NJE7FdnwGOkz6g,4187
21
+ devpace-1.0.0.dist-info/METADATA,sha256=PlOnBIc_tZweODB0G_I1gYbM0eBfv4nge7BeZBpgN9s,544
22
+ devpace-1.0.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
23
+ devpace-1.0.0.dist-info/licenses/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
24
+ devpace-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.