optimal goaltest TODO
This commit is contained in:
parent
06e30867c3
commit
56bebed942
@ -3,7 +3,7 @@
|
|||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="56453584-72bd-49f4-a39c-fccf91ab20c6" name="Default Changelist" comment="">
|
<list default="true" id="56453584-72bd-49f4-a39c-fccf91ab20c6" name="Default Changelist" comment="">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/plant.py" beforeDir="false" afterPath="$PROJECT_DIR$/plant.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/map.py" beforeDir="false" afterPath="$PROJECT_DIR$/map.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/py.py" beforeDir="false" afterPath="$PROJECT_DIR$/py.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/py.py" beforeDir="false" afterPath="$PROJECT_DIR$/py.py" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
@ -114,6 +114,11 @@
|
|||||||
<workItem from="1618060647009" duration="10450000" />
|
<workItem from="1618060647009" duration="10450000" />
|
||||||
<workItem from="1618073000111" duration="1948000" />
|
<workItem from="1618073000111" duration="1948000" />
|
||||||
<workItem from="1618075018240" duration="1221000" />
|
<workItem from="1618075018240" duration="1221000" />
|
||||||
|
<workItem from="1618076449045" duration="53000" />
|
||||||
|
<workItem from="1618081569163" duration="130000" />
|
||||||
|
<workItem from="1618219455026" duration="134000" />
|
||||||
|
<workItem from="1619199327277" duration="68000" />
|
||||||
|
<workItem from="1619200872847" duration="13871000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
@ -125,42 +130,42 @@
|
|||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state x="690" y="287" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog/0.0.1920.1080@0.0.1920.1080" timestamp="1617994393023" />
|
<state x="690" y="287" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog/0.0.1920.1080@0.0.1920.1080" timestamp="1617994393023" />
|
||||||
<state width="1879" height="295" key="GridCell.Tab.0.bottom" timestamp="1618076242344">
|
<state width="1879" height="364" key="GridCell.Tab.0.bottom" timestamp="1619215367013">
|
||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state width="1879" height="295" key="GridCell.Tab.0.bottom/0.0.1920.1080@0.0.1920.1080" timestamp="1618076242344" />
|
<state width="1879" height="364" key="GridCell.Tab.0.bottom/0.0.1920.1080@0.0.1920.1080" timestamp="1619215367013" />
|
||||||
<state width="1879" height="295" key="GridCell.Tab.0.center" timestamp="1618076242344">
|
<state width="1879" height="364" key="GridCell.Tab.0.center" timestamp="1619215367013">
|
||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state width="1879" height="295" key="GridCell.Tab.0.center/0.0.1920.1080@0.0.1920.1080" timestamp="1618076242344" />
|
<state width="1879" height="364" key="GridCell.Tab.0.center/0.0.1920.1080@0.0.1920.1080" timestamp="1619215367013" />
|
||||||
<state width="1879" height="295" key="GridCell.Tab.0.left" timestamp="1618076242344">
|
<state width="1879" height="364" key="GridCell.Tab.0.left" timestamp="1619215367013">
|
||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state width="1879" height="295" key="GridCell.Tab.0.left/0.0.1920.1080@0.0.1920.1080" timestamp="1618076242344" />
|
<state width="1879" height="364" key="GridCell.Tab.0.left/0.0.1920.1080@0.0.1920.1080" timestamp="1619215367013" />
|
||||||
<state width="1879" height="295" key="GridCell.Tab.0.right" timestamp="1618076242344">
|
<state width="1879" height="364" key="GridCell.Tab.0.right" timestamp="1619215367013">
|
||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state width="1879" height="295" key="GridCell.Tab.0.right/0.0.1920.1080@0.0.1920.1080" timestamp="1618076242344" />
|
<state width="1879" height="364" key="GridCell.Tab.0.right/0.0.1920.1080@0.0.1920.1080" timestamp="1619215367013" />
|
||||||
<state width="1879" height="364" key="GridCell.Tab.1.bottom" timestamp="1618074966357">
|
<state width="1879" height="364" key="GridCell.Tab.1.bottom" timestamp="1619215367013">
|
||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state width="1879" height="364" key="GridCell.Tab.1.bottom/0.0.1920.1080@0.0.1920.1080" timestamp="1618074966357" />
|
<state width="1879" height="364" key="GridCell.Tab.1.bottom/0.0.1920.1080@0.0.1920.1080" timestamp="1619215367013" />
|
||||||
<state width="1879" height="364" key="GridCell.Tab.1.center" timestamp="1618074966357">
|
<state width="1879" height="364" key="GridCell.Tab.1.center" timestamp="1619215367013">
|
||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state width="1879" height="364" key="GridCell.Tab.1.center/0.0.1920.1080@0.0.1920.1080" timestamp="1618074966357" />
|
<state width="1879" height="364" key="GridCell.Tab.1.center/0.0.1920.1080@0.0.1920.1080" timestamp="1619215367013" />
|
||||||
<state width="1879" height="364" key="GridCell.Tab.1.left" timestamp="1618074966357">
|
<state width="1879" height="364" key="GridCell.Tab.1.left" timestamp="1619215367013">
|
||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state width="1879" height="364" key="GridCell.Tab.1.left/0.0.1920.1080@0.0.1920.1080" timestamp="1618074966357" />
|
<state width="1879" height="364" key="GridCell.Tab.1.left/0.0.1920.1080@0.0.1920.1080" timestamp="1619215367013" />
|
||||||
<state width="1879" height="364" key="GridCell.Tab.1.right" timestamp="1618074966357">
|
<state width="1879" height="364" key="GridCell.Tab.1.right" timestamp="1619215367013">
|
||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state width="1879" height="364" key="GridCell.Tab.1.right/0.0.1920.1080@0.0.1920.1080" timestamp="1618074966357" />
|
<state width="1879" height="364" key="GridCell.Tab.1.right/0.0.1920.1080@0.0.1920.1080" timestamp="1619215367013" />
|
||||||
<state x="0" y="0" key="com.intellij.ide.util.TipDialog" timestamp="1618075018440">
|
<state x="0" y="0" key="com.intellij.ide.util.TipDialog" timestamp="1618219454594">
|
||||||
<screen x="0" y="0" width="1920" height="1080" />
|
<screen x="0" y="0" width="1920" height="1080" />
|
||||||
</state>
|
</state>
|
||||||
<state x="0" y="0" key="com.intellij.ide.util.TipDialog/0.0.1920.1080@0.0.1920.1080" timestamp="1618075018440" />
|
<state x="0" y="0" key="com.intellij.ide.util.TipDialog/0.0.1920.1080@0.0.1920.1080" timestamp="1618219454594" />
|
||||||
</component>
|
</component>
|
||||||
<component name="XDebuggerManager">
|
<component name="XDebuggerManager">
|
||||||
<breakpoint-manager>
|
<breakpoint-manager>
|
||||||
@ -174,6 +179,6 @@
|
|||||||
</breakpoint-manager>
|
</breakpoint-manager>
|
||||||
</component>
|
</component>
|
||||||
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
||||||
<SUITE FILE_PATH="coverage/SmartTractor$py.coverage" NAME="py Coverage Results" MODIFIED="1618076215552" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
<SUITE FILE_PATH="coverage/SmartTractor$py.coverage" NAME="py Coverage Results" MODIFIED="1619214699579" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
BIN
__pycache__/astar.cpython-37.pyc
Normal file
BIN
__pycache__/astar.cpython-37.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
128
astar.py
Normal file
128
astar.py
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
from operator import itemgetter
|
||||||
|
import copy
|
||||||
|
import tractor
|
||||||
|
class Istate: #stan początkowy traktora (strona, w którą patrzy, miejsce, w którym się on znajduje)
|
||||||
|
def __init__(self, direction, x, y):
|
||||||
|
self.direction = direction
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
def get_direction(self):
|
||||||
|
return self.direction
|
||||||
|
def set_direction(self, direction):
|
||||||
|
self.direction = direction
|
||||||
|
def get_x(self):
|
||||||
|
return self.x
|
||||||
|
def set_x(self, x):
|
||||||
|
self.x = x
|
||||||
|
def get_y(self):
|
||||||
|
return self.y
|
||||||
|
def set_y(self, y):
|
||||||
|
self.y = y
|
||||||
|
class Node: #wierzchołek grafu
|
||||||
|
def __init__(self, action, direction, parent, x, y):
|
||||||
|
self.action = action #akcja jaką ma wykonać (obróc się w lewo, obróć się w prawo, ruch do przodu)
|
||||||
|
self.direction = direction
|
||||||
|
self.parent = parent #ojciec wierzchołka
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
def get_action(self):
|
||||||
|
return self.action
|
||||||
|
def set_action(self, action):
|
||||||
|
self.action = action
|
||||||
|
def get_direction(self):
|
||||||
|
return self.direction
|
||||||
|
def set_direction(self, direction):
|
||||||
|
self.direction = direction
|
||||||
|
def get_parent(self):
|
||||||
|
return self.parent
|
||||||
|
def set_parent(self, parent):
|
||||||
|
self.parent = parent
|
||||||
|
def get_x(self):
|
||||||
|
return self.x
|
||||||
|
def set_x(self, x):
|
||||||
|
self.x = x
|
||||||
|
def get_y(self):
|
||||||
|
return self.y
|
||||||
|
def set_y(self, y):
|
||||||
|
self.y = y
|
||||||
|
def cost(map, node): #funkcja kosztu : ile kosztuje przejechanie przez dane pole
|
||||||
|
return map.get_field_cost(int(node.get_x()), int(node.get_y()))
|
||||||
|
def heuristic(node, goaltest): #funkcja heurestyki : oszacowuje koszt osiągnięcia stanu końcowego (droga)
|
||||||
|
return abs(node.get_x() - goaltest[0]) + abs(node.get_y() - goaltest[1])
|
||||||
|
def f(map, node, goaltest): #funkcja zwracająca sumę funkcji kosztu oraz heurestyki
|
||||||
|
return cost(map, node) + heuristic(node, goaltest)
|
||||||
|
# def optimal_goal_test():
|
||||||
|
|
||||||
|
def goal_test(elem, goaltest): #funkcja sprawdzająca czy położenie traktora równa się położeniu punktu docelowego, jeśli tak zwraca prawdę, w przeciwnym wypadku fałsz
|
||||||
|
if elem.get_x() == goaltest[0] and elem.get_y() == goaltest[1]:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
def print_moves(elem): #zwraca listę ruchów jakie należy wykonać by dotrzeć do punktu docelowego
|
||||||
|
moves_list = []
|
||||||
|
while (elem[0].get_parent() != None):
|
||||||
|
moves_list.append(elem[0].get_action())
|
||||||
|
elem = elem[0].get_parent()
|
||||||
|
moves_list.reverse()
|
||||||
|
return moves_list
|
||||||
|
def succ(elem): #funkcja następnika, przypisuje jakie akcje są możliwe do wykonania na danym polu oraz jaki będzie stan (kierunek, położenie) po wykonaniu tej akcji
|
||||||
|
actions_list = []
|
||||||
|
temp = copy.copy(elem.get_direction())
|
||||||
|
if temp == 1:
|
||||||
|
temp = 4
|
||||||
|
else:
|
||||||
|
temp = temp - 1
|
||||||
|
actions_list.append(("rotate_left", (temp, elem.get_x(), elem.get_y())))
|
||||||
|
temp = copy.copy(elem.get_direction())
|
||||||
|
if temp == 4:
|
||||||
|
temp = 1
|
||||||
|
else:
|
||||||
|
temp = temp + 1
|
||||||
|
actions_list.append(("rotate_right", (temp, elem.get_x(), elem.get_y())))
|
||||||
|
temp_move_south = elem.get_y() + 1
|
||||||
|
temp_move_west = elem.get_x() - 1
|
||||||
|
temp_move_east = elem.get_x() + 1
|
||||||
|
temp_move_north = elem.get_y() - 1
|
||||||
|
if tractor.Tractor.is_move_allowed_succ(elem) == "x + 1":
|
||||||
|
actions_list.append(("move", (elem.get_direction(), temp_move_east, elem.get_y())))
|
||||||
|
elif tractor.Tractor.is_move_allowed_succ(elem) == "y - 1":
|
||||||
|
actions_list.append(("move", (elem.get_direction(), elem.get_x(), temp_move_north)))
|
||||||
|
elif tractor.Tractor.is_move_allowed_succ(elem) == "y + 1":
|
||||||
|
actions_list.append(("move", (elem.get_direction(), elem.get_x(), temp_move_south)))
|
||||||
|
elif tractor.Tractor.is_move_allowed_succ(elem) == "x - 1":
|
||||||
|
actions_list.append(("move", (elem.get_direction(), temp_move_west, elem.get_y())))
|
||||||
|
return actions_list
|
||||||
|
def graphsearch(fringe, explored, istate, succ, goaltest, f, map): #przeszukiwanie grafu wszerz
|
||||||
|
node = Node(None, istate.get_direction(), None, istate.get_x(), istate.get_y()) #wierzchołek początkowy, stworzony ze stanu początkowego traktora
|
||||||
|
fringe.append((node, 0)) #wierzchołki do odwiedzenia z priorytetem
|
||||||
|
while True:
|
||||||
|
if not fringe:
|
||||||
|
return False
|
||||||
|
elem = fringe.pop(0) #zdejmujemy wierzchołek z kolejki fringe i rozpatrujemy go
|
||||||
|
temp = copy.copy(elem[0])
|
||||||
|
if goal_test(elem[0], goaltest) is True: #jeżeli osiągniemy cel w trakcie przeszukiwania grafu wszerz (wjedziemy na pole docelowe) : zwracamy listę ruchów, po których wykonaniu dotrzemy na miejsce
|
||||||
|
return print_moves(elem)
|
||||||
|
explored.append(elem) #dodajemy wierzchołek do listy wierzchołków odwiedzonych
|
||||||
|
for (action, state) in succ(temp): #iterujemy po wszystkich możliwych akcjach i stanach otrzymanych dla danego wierzchołka grafu
|
||||||
|
fringe_tuple = []
|
||||||
|
fringe_tuple_prio = []
|
||||||
|
explored_tuple = []
|
||||||
|
for (x, y) in fringe:
|
||||||
|
fringe_tuple.append((x.get_direction(), x.get_x(), x.get_y()))
|
||||||
|
fringe_tuple_prio.append(((x.get_direction(), x.get_x(), x.get_y()), y))
|
||||||
|
for (x, y) in explored:
|
||||||
|
explored_tuple.append((x.get_direction(), x.get_x(), x.get_y()))
|
||||||
|
x = Node(action, state[0], elem, state[1], state[2]) #stworzenie nowego wierzchołka, którego rodzicem jest elem
|
||||||
|
p = f(map, x, goaltest) #liczy priorytet
|
||||||
|
if state not in fringe_tuple and state not in explored_tuple: #jeżeli stan nie znajduje się na fringe oraz nie znajduje się w liście wierzchołków odwiedzonych
|
||||||
|
fringe.append((x, p)) #dodanie wierzchołka na fringe
|
||||||
|
fringe = sorted(fringe, key=itemgetter(1)) #sortowanie fringe'a według priorytetu
|
||||||
|
elif state in fringe_tuple:
|
||||||
|
i = 0
|
||||||
|
for (state_prio, r) in fringe_tuple_prio:
|
||||||
|
if str(state_prio) == str(state):
|
||||||
|
if r > p:
|
||||||
|
fringe.insert(i, (x, p)) #zamiana state, który należy do fringe z priorytetem r na state z priorytetem p (niższym)
|
||||||
|
fringe = sorted(fringe, key=itemgetter(1)) #sortowanie fringe'a według priorytetu
|
||||||
|
break
|
||||||
|
i = i + 1
|
26
map.py
26
map.py
@ -23,6 +23,32 @@ class Map:
|
|||||||
temp_field = field.Field(temp_plant, temp_rect, temp_soil)
|
temp_field = field.Field(temp_plant, temp_rect, temp_soil)
|
||||||
temp_map_field.append(temp_field)
|
temp_map_field.append(temp_field)
|
||||||
self.fields.append(temp_map_field)
|
self.fields.append(temp_map_field)
|
||||||
|
def get_field_cost(self, x, y): #zwraca koszt danego pola
|
||||||
|
field = self.fields[x][y]
|
||||||
|
if field.get_plant().get_name() == "station" and field.get_plant().get_state() == -1:
|
||||||
|
return 5
|
||||||
|
elif field.get_plant().get_name() == "beetroot" and field.get_plant().get_state() > 0 and field.get_plant().get_state() <= 3 * definitions.BEETROOTS_GROW_TIME:
|
||||||
|
return 10
|
||||||
|
elif field.get_plant().get_name() == "beetroot" and field.get_plant().get_state() == definitions.BEETROOTS_MAXIMUM_STATE:
|
||||||
|
return 4
|
||||||
|
elif field.get_plant().get_name() == "carrot" and field.get_plant().get_state() > 0 and field.get_plant().get_state() <= 3 * definitions.CARROTS_GROW_TIME:
|
||||||
|
return 10
|
||||||
|
elif field.get_plant().get_name() == "carrot" and field.get_plant().get_state() == definitions.CARROTS_MAXIMUM_STATE:
|
||||||
|
return 4
|
||||||
|
elif field.get_plant().get_name() == "potato" and field.get_plant().get_state() > 0 and field.get_plant().get_state() <= 3 * definitions.POTATOES_GROW_TIME:
|
||||||
|
return 10
|
||||||
|
elif field.get_plant().get_name() == "potato" and field.get_plant().get_state() == definitions.POTATOES_MAXIMUM_STATE:
|
||||||
|
return 4
|
||||||
|
elif field.get_plant().get_name() == "wheat" and field.get_plant().get_state() > 0 and field.get_plant().get_state() <= 7 * definitions.WHEAT_GROW_TIME:
|
||||||
|
return 10
|
||||||
|
elif field.get_plant().get_name() == "wheat" and field.get_plant().get_state() == definitions.WHEAT_MAXIMUM_STATE:
|
||||||
|
return 4
|
||||||
|
elif field.get_soil().get_state() is False:
|
||||||
|
return 2
|
||||||
|
elif field.get_soil().get_state() is True and field.get_soil().get_water_level() is False:
|
||||||
|
return 3
|
||||||
|
elif field.get_soil().get_state() is True and field.get_soil().get_water_level() is True:
|
||||||
|
return 1
|
||||||
def fill_map(self): #wypełnia mapę teksturami na podstawie logicznego stanu pól
|
def fill_map(self): #wypełnia mapę teksturami na podstawie logicznego stanu pól
|
||||||
for i in range(definitions.WIDTH_AMOUNT):
|
for i in range(definitions.WIDTH_AMOUNT):
|
||||||
for j in range(definitions.HEIGHT_AMOUNT):
|
for j in range(definitions.HEIGHT_AMOUNT):
|
||||||
|
4
py.py
4
py.py
@ -1,3 +1,4 @@
|
|||||||
|
import astar
|
||||||
import definitions
|
import definitions
|
||||||
import graph
|
import graph
|
||||||
import map
|
import map
|
||||||
@ -27,7 +28,8 @@ def main():
|
|||||||
map1.draw_window(tractor1, tractor1_rect)
|
map1.draw_window(tractor1, tractor1_rect)
|
||||||
if not move_list and plant.Plant.if_any_mature_plant(map1) is True: #jeżeli są jakieś ruchy do wykonania w move_list oraz istnieje jakaś dojrzała roślina
|
if not move_list and plant.Plant.if_any_mature_plant(map1) is True: #jeżeli są jakieś ruchy do wykonania w move_list oraz istnieje jakaś dojrzała roślina
|
||||||
istate = graph.Istate(tractor1.get_direction(), tractor1.get_x() / definitions.BLOCK_SIZE, tractor1.get_y() / definitions.BLOCK_SIZE) #stan początkowy traktora (jego orientacja oraz jego aktualne współrzędne)
|
istate = graph.Istate(tractor1.get_direction(), tractor1.get_x() / definitions.BLOCK_SIZE, tractor1.get_y() / definitions.BLOCK_SIZE) #stan początkowy traktora (jego orientacja oraz jego aktualne współrzędne)
|
||||||
move_list = (graph.graphsearch([], [], istate, graph.succ, plant.Plant.get_closest_mature_plant(map1, tractor1))) #lista z ruchami, które należy po kolei wykonać
|
#move_list = (graph.graphsearch([], [], istate, graph.succ, plant.Plant.get_closest_mature_plant(map1, tractor1))) #lista z ruchami, które należy po kolei wykonać, graph
|
||||||
|
move_list = (astar.graphsearch([], [], istate, graph.succ, plant.Plant.get_closest_mature_plant(map1, tractor1), astar.f, map1)) #lista z ruchami, które należy po kolei wykonać, astar
|
||||||
elif move_list: #jeżeli move_list nie jest pusta
|
elif move_list: #jeżeli move_list nie jest pusta
|
||||||
tractor1.handle_movement(move_list.pop(0), tractor1_rect) #wykonaj kolejny ruch oraz zdejmij ten ruch z początku listy
|
tractor1.handle_movement(move_list.pop(0), tractor1_rect) #wykonaj kolejny ruch oraz zdejmij ten ruch z początku listy
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user