-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcube_state.py
129 lines (99 loc) · 4.86 KB
/
cube_state.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import copy
from snake_description import SnakeDescription, Direction
class CubeState:
datatype = np.dtype((np.int32, (3,))) # datatyp for 3D integer points
def __init__(self, description):
# snake description
self.snake_description = description
# create memory for points
self.points = np.zeros(self.snake_description.cube_size**3,dtype=self.datatype) # points that are occupied by the snake
self.current_point = np.zeros(1, CubeState.datatype) # current position
self.current_points_index = 0 # index of last written array place
# insert the first segment
self.current_seg = 0 # index of lastly expanded segment (0: first segment)
self.current_dir = Direction.Xp # direction
self.appendSegment(self.current_seg, self.current_dir)
# insert the second segment (since the second segment determines the rotations)
self.current_seg += 1
self.current_dir = Direction.Yp
self.appendSegment(self.current_seg, self.current_dir)
def plotState(self):
#print(self.points)
figure = plt.figure(0)
ax = figure.gca(projection='3d')
x = self.points[0:self.current_points_index+1, 0]
y = self.points[0:self.current_points_index+1, 1]
z = self.points[0:self.current_points_index+1, 2]
plt.cla()
limit = self.snake_description.cube_size + 1
ax.set_xlim(-limit, limit)
ax.set_ylim(-limit, limit)
ax.set_zlim(-limit, limit)
ax.set_facecolor('green' if self.isValid() else 'red')
ax.plot(x,y,z, color='black', linewidth=3)
#plt.ion()
plt.show()
#plt.pause(0.001)
def isValid(self):
valid_points = self.points[0:self.current_points_index+1]
minima = np.amin(valid_points, axis=0)
maxima = np.amax(valid_points, axis=0)
delta = maxima-minima # size in x,y,z-direciton
unique_points = np.unique(valid_points, axis=0) # unique points
# cube state is valid if dimensions are not exceeded and points are unique
if (max(delta) < self.snake_description.cube_size
and unique_points.shape[0] == valid_points.shape[0]):
return True
else:
return False
def isComplete(self):
complete = (self.current_seg+1 == len(self.snake_description.segment_lengths))
return complete
def appendSegment(self, seg_num, dir):
# kind of a switch case
dir_vec = {
Direction.Xn : (-1,0,0),
Direction.Xp : (+1,0,0),
Direction.Yn : (0,-1,0),
Direction.Yp : (0,+1,0),
Direction.Zn : (0,0,-1),
Direction.Zp : (0,0,+1)
}[dir]
seg_length = self.snake_description.segment_lengths[seg_num]
# special treatment for first segment
if seg_num == 0:
seg_length -= 1
# add specified amount of cubes to list
for _ in range(0,seg_length):
self.current_point += dir_vec
self.current_points_index += 1
self.points[self.current_points_index,:] = self.current_point
def extend(self, variant):
if variant > 3:
raise Exception("Only four variants are available!")
self.current_dir = {
Direction.Xp : [Direction.Yp, Direction.Zp, Direction.Yn, Direction.Zn],
Direction.Xn : [Direction.Zn, Direction.Yn, Direction.Zp, Direction.Yp],
Direction.Yp : [Direction.Zp, Direction.Xp, Direction.Zn, Direction.Xn],
Direction.Yn : [Direction.Xn, Direction.Zn, Direction.Xp, Direction.Zp],
Direction.Zp : [Direction.Xp, Direction.Yp, Direction.Xn, Direction.Yn],
Direction.Zn : [Direction.Yn, Direction.Xn, Direction.Yp, Direction.Xp],
}[self.current_dir][variant]
self.current_seg += 1
if self.current_seg >= len(self.snake_description.segment_lengths):
raise Exception("Called extend on a snake that is already fully used.")
self.appendSegment(self.current_seg, self.current_dir)
# custom deep copy method to avoid copying of the snake description in depth first search
def __deepcopy__(self, memo):
copied = CubeState.__new__(CubeState)
copied.snake_description = self.snake_description # description is only copied as reference
# the state determining fields are truly copied (deep copy)
copied.points = copy.deepcopy(self.points, memo)
copied.current_point = copy.deepcopy(self.current_point, memo)
copied.current_points_index = copy.deepcopy(self.current_points_index, memo)
copied.current_seg = copy.deepcopy(self.current_seg, memo)
copied.current_dir = copy.deepcopy(self.current_dir, memo)
return copied