From eb87ec9f3748ecc08c0d85a21117481be1a79416 Mon Sep 17 00:00:00 2001 From: Kraton99 Date: Mon, 12 Apr 2021 22:54:33 +0200 Subject: [PATCH] added pathfind --- .idea/Projekt_AI-Automatyczny_saper.iml | 2 +- .idea/misc.xml | 2 +- Engine/Board.py | 9 ++ Engine/Game.py | 63 ++++++++++---- Engine/PathFinder.py | 78 ++++++++++++++++++ Engine/Point.py | 3 + Engine/__pycache__/Agent.cpython-39.pyc | Bin 894 -> 894 bytes Engine/__pycache__/Board.cpython-39.pyc | Bin 1809 -> 2176 bytes Engine/__pycache__/Bomb.cpython-39.pyc | Bin 518 -> 518 bytes Engine/__pycache__/BombFactory.cpython-39.pyc | Bin 816 -> 816 bytes Engine/__pycache__/Game.cpython-39.pyc | Bin 2512 -> 2982 bytes Engine/__pycache__/PathFinder.cpython-39.pyc | Bin 0 -> 2367 bytes Engine/__pycache__/Point.cpython-39.pyc | Bin 1185 -> 1361 bytes Engine/__pycache__/Stone.cpython-39.pyc | Bin 429 -> 429 bytes __pycache__/Constants.cpython-39.pyc | Bin 545 -> 545 bytes main.py | 2 + 16 files changed, 139 insertions(+), 20 deletions(-) create mode 100644 Engine/PathFinder.py create mode 100644 Engine/__pycache__/PathFinder.cpython-39.pyc diff --git a/.idea/Projekt_AI-Automatyczny_saper.iml b/.idea/Projekt_AI-Automatyczny_saper.iml index 4c879079..ba6cfa6f 100644 --- a/.idea/Projekt_AI-Automatyczny_saper.iml +++ b/.idea/Projekt_AI-Automatyczny_saper.iml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9dfb2a91..2d83d70f 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/Engine/Board.py b/Engine/Board.py index d837a6b0..b07afa93 100644 --- a/Engine/Board.py +++ b/Engine/Board.py @@ -8,6 +8,7 @@ class Board: def __init__(self, win): self.board = [] self.bombMap = {} + self.stoneMap = {} self.win = win def drawSquares(self, win): @@ -33,6 +34,14 @@ class Board: rect.center = (key.getX() * SQUARE_SIZE + SQUARE_SIZE / 2, key.getY() * SQUARE_SIZE + SQUARE_SIZE / 2) self.win.blit(image, rect) + def drawStones(self): + for key in self.stoneMap: + image = pygame.image.load('Engine/stone.png') + image = pygame.transform.scale(image, (SQUARE_SIZE - 5, SQUARE_SIZE - 5)) + rect = image.get_rect() + rect.center = (key.getX() * SQUARE_SIZE + SQUARE_SIZE / 2, key.getY() * SQUARE_SIZE + SQUARE_SIZE / 2) + self.win.blit(image, rect) + def getBomb(self, point): if point in self.bombMap: return self.bombMap[point] diff --git a/Engine/Game.py b/Engine/Game.py index c91e31c8..9915984e 100644 --- a/Engine/Game.py +++ b/Engine/Game.py @@ -8,6 +8,7 @@ from Engine.Agent import Agent from Engine.BombFactory import BombFactory from Engine.Point import Point from Engine.Stone import Stone +from Engine.PathFinder import PathFinder class Game: @@ -27,35 +28,55 @@ class Game: self.agent.defuse(self.board.getBomb(self.agent.getPoint())) self.board.drawSquares(self.win) self.board.drawBombs() + self.board.drawStones() self.board.drawAgent(self.win, self.agent) pygame.display.update() def move(self): - point = self.agent.getPoint() - if self.goingDown: - if point.getY() + 1 < ROWS: - point.y += 1 - elif point.getX() + 1 < COLS: - point.x += 1 - self.goingDown = not self.goingDown - else: - if point.getY() - 1 >= 0: - point.y -= 1 - elif point.getX() + 1 < COLS: - point.x += 1 - self.goingDown = not self.goingDown - self.agent.point = point + # point = self.agent.getPoint() + # if self.goingDown: + # if point.getY() + 1 < ROWS: + # point.y += 1 + # elif point.getX() + 1 < COLS: + # point.x += 1 + # self.goingDown = not self.goingDown + # else: + # if point.getY() - 1 >= 0: + # point.y -= 1 + # elif point.getX() + 1 < COLS: + # point.x += 1 + # self.goingDown = not self.goingDown + # self.agent.point = point + self.moveSequence() + + def moveSequence(self): + pathfinder = PathFinder(self.board) + for point in pathfinder.findPath(Point(0,0), Point(5,5)): + self.agent.point = point + self.update() + def randomizeObject(self): i = 0 - while i < 11: - point = Point(random.randint(0, 7), random.randint(0, 7)) + while i < 5: + point = Point(random.randint(0, 9), random.randint(0, 9)) if(point.getX() == 0 and point.getY() == 0): continue; if point not in self.board.bombMap: object = self.pickObject(random.randint(0, 4)) self.board.bombMap[point] = object i += 1 + r = 15 + j = 0 + while j < r: + point = Point(random.randint(0, 9), random.randint(0, 9)) + if (point.getX() == 0 and point.getY() == 0): + continue; + if point not in self.board.bombMap and point not in self.board.stoneMap: + object = Stone() + self.board.stoneMap[point] = object + j += 1 + def pickObject(self, rand): if rand == 0: @@ -68,5 +89,11 @@ class Game: return BombFactory.create(CLAYMORE) elif rand == 4: return BombFactory.create(LAND_MINE) - # elif(rand == 5): - # return Stone() + + def finalState(self): + j = 0 + for key in self.board.bombMap: + bomb = self.board.bombMap[key] + if not bomb.isDefused: + j += 1 + return j == 0 diff --git a/Engine/PathFinder.py b/Engine/PathFinder.py new file mode 100644 index 00000000..fc67ef5c --- /dev/null +++ b/Engine/PathFinder.py @@ -0,0 +1,78 @@ +from Constants import ROWS, COLS +from Engine.Point import Point + + +class PathFinder: + + def __init__(self, board): + self.board = board + self.openList = [] + self.cameFrom = {} + self.gScore = {} + self.fScore = {} + self.current = Point(0,0) + + + def findPath(self,startPoint, endPoint): + self.openList.append(startPoint) + self.gScore[startPoint] = 0 + self.fScore[startPoint] = startPoint.distance(endPoint) + + while self.openList: + self.current = self.minKey(self.fScore, self.openList) + + if self.current.__eq__(endPoint): + return self.reconstructPath() + + self.openList.remove(self.current) + + for point in self.getNeighbour(self.current): + tentativeGScore = self.gScore.get(self.current) + self.current.distance(point) + if tentativeGScore < self.gScore.get(point, 10000): + self.cameFrom[point] = self.current + self.gScore[point] = tentativeGScore + self.fScore[point] = point.distance(startPoint) + if(point not in self.openList): + self.openList.append(point) + return [] + + def reconstructPath(self): + totalPath = [] + totalPath.append(self.current) + while self.current in self.cameFrom: + self.current = self.cameFrom[self.current] + totalPath.insert(0,self.current) + return totalPath + + def getNeighbour(self, current): + neighbourlist = [] + point1 = Point(current.getX() + 1, current.getY()) + point2 = Point(current.getX(), current.getY() + 1) + point3 = Point(current.getX(), current.getY() - 1) + point4 = Point(current.getX() - 1, current.getY()) + if not (point1.getX() < 0 or point1.getX() > COLS or point1.getY() < 0 or point1.getY() > ROWS or point1.__eq__(current)) and point1 not in self.board.stoneMap: + neighbourlist.append(point1) + if not (point2.getX() < 0 or point2.getX() > COLS or point2.getY() < 0 or point2.getY() > ROWS or point2.__eq__(current)) and point2 not in self.board.stoneMap: + neighbourlist.append(point2) + if not (point3.getX() < 0 or point3.getX() > COLS or point3.getY() < 0 or point3.getY() > ROWS or point3.__eq__(current)) and point3 not in self.board.stoneMap: + neighbourlist.append(point3) + if not (point4.getX() < 0 or point4.getX() > COLS or point4.getY() < 0 or point4.getY() > ROWS or point4.__eq__(current)) and point4 not in self.board.stoneMap: + neighbourlist.append(point4) + + return neighbourlist + + + def minKey(self, fscore, openlist): + minkey = Point(0,0) + minValue = float('inf') + for point in openlist: + value = fscore.get(point, 10000) + if value < minValue: + minValue = value + minkey = point + return minkey + + + + + diff --git a/Engine/Point.py b/Engine/Point.py index 3d872721..0f15323e 100644 --- a/Engine/Point.py +++ b/Engine/Point.py @@ -9,6 +9,9 @@ class Point: def getX(self): return self.x + def distance(self,endpoint): + return abs(self.getX() + endpoint.getX()) + abs(self.getY() + endpoint.getY()) + def __hash__(self): """Overrides the default implementation""" return hash(tuple(sorted(self.__dict__.items()))) diff --git a/Engine/__pycache__/Agent.cpython-39.pyc b/Engine/__pycache__/Agent.cpython-39.pyc index 2e269567b125829527b852c6dfd3535993543efd..91bc5844d9c837c408a9805b6145b2a5c70eeb53 100644 GIT binary patch delta 20 acmeyz_K%G_k(ZZ?0SNqBOEz*BGXnrRC_kaZJ6)$lRE~-e zFA(jKOLF8bcmpc+<}>2NLonlr6cEMI{_@Yx%+Bo0j_mhywp%D<8GinU{+?%z>@ToB z`uZsE{ z^~1m?r48DF!xKI7yG>cZ!#*=vQ~~T+g3^Pj&fxT+jWV?+nhXbt_9pDgBJHIpp-OU| zbO&39N3QfETb=PwFt0-G`EQ|y+wz0HT$sh32WKew37O04yY|hbTgiEKs$VwCBp1~W zeRcaf$tA)v;U0s%-L@VeRQCbFB$ir0-P=({t20gCY%uOld)$Mc^ zMlWpR#Q%CJR?F{G^B<_9c>^+P&0N`@qY^3v$|0+SRYHw$e!%R>$P5}xTxmUm3sYFQ kvO=U5Cnw8lVs765M`$9}4?^##>p!NsM|6mQCCF<(0k^HL{{R30 delta 537 zcmZ{hy-ve05Xa*rPTY^AtyD3TqJF3hfes9?AtX={Q(1}_y3n+7tBBGRr&Wa1fdwSS z)&m1izyq-J1~7YO?IR%J%K)eX4?my$zyJBpzRk^T+qJBuA{SlsIxl!`zoOmw+n(N1 zoHWm(%JG`i2FgsiP<$YoAxYI!WCA*MG=aN;%RFIrgR5@S9Sbe;M~*7=kPiDSEzQpg zv-v&hU<0n8ss{L?tE#b!JXeA)8KsOEr9AiKsRvxEqLG&h@B zs9gZm01luI`0;+f6-!6~9yf%KBr3tgBnC;w=T3^{d6qQle;5VXzY4tRkRBj#LkWV) HD6M?~S5R%z diff --git a/Engine/__pycache__/Bomb.cpython-39.pyc b/Engine/__pycache__/Bomb.cpython-39.pyc index 0d1307365785cf74de02e2c711652a28f5361fde..330ee454d0d2b83c36b3555c4bdcf47d1c383f3c 100644 GIT binary patch delta 20 acmZo;X=C9|H!XsIPfR%-nfa0#jf6)w{PCey!V^m+h?94K} zsdK9mefvp0kiOcaUHP+&3@eX{QJT|Ux957%pYw$r9wT;3K zIIzfRObl`~Cs~=Pv$)8eR4?J++0x(I3w?EoJ~A~w`moikddXFD?k=T+d8*2N@`acx zn&qe!_~Fp~LCp^$Rl+c}Kxz@yBTyH}9?O%aC??FIVo-uSILXiEQV;Nx@c9TuPsVJ( zPG<^fuGzZhm;LshA8h*SWegqLKQ$?W3JPg6R_J6mDouZtyqk2y@nfK2qv+$-80)c! z@Pa;cA%+2u3<(nYG;+!N{D7~sJH;-KIYyb^SeTtn*|jeblCE)6(e6hUDmSBwI1G^# zTSx_>gqk5AWtLjIc$JYx$u%@eo>Se$7>f0kdW|B-a9cs&+bE$x#lV3@5YU-EDef4Q zQ$6^MFa%=ITj1)+JgE`yQxcTaX=P z`>bok1_EF;M9kM%Y)R`H>sswtgOC}5pkBpekFumpQW}^7TCSr(NNrUKWUJ|AXsidb zk!K>`zSR0F4O^N#w~IYbghaB>D!XcymfISu6zUqG)NWN9{$`YdN}(~1*Ew8p9VL7P z6$2B|D#1K($iWPXgPxIZ9&Ge=iW<#fa`ld%+{iqfx{Rxjh)PGq81;JcS7vpIi0zpa zIDYI^oVlI6DX#QRT?FAk>owcx8u1Q*nz8{%s|!dgZO8naM!3PlTnv&Uw$LUEZ)QX? zML8jHs8iJ{Dlc0P*LC+w*Bo};Tc4vpHMaflJ+q2UJC}5q-6_OujRy@+jdHDgnaA zSBPnm5obkC&${Q;6^bk+&&BUwc+(#TwR+&Mj((}b&Z3R}?}SvWHCu9T$A6DF7gEOw ME?|vQSubAWUqv7)FaQ7m delta 1011 zcma)5%}>-&5P#ElyRY44vq3%=1W{2c5%HoXt|op&y@*6&BE8^3>t+{eVOj*u8V-6h zA>zBC2iAiL96b3ic=zO?Cp~UFdG+K>0i(o&eVJcp<~MKNbmsMa_vb@}N?V&P==u73 z?m?HeQRs)wjnS7KH-#rX>xJ;F=bBscU`jal#+Mzn4kak7ZMbBRr=Whqy6mRi+X4sF zE6s(1`mSvbCssAA1=Z`}N`U=D>IX6Q5``s(J^}|$;$b!p6v-S1MQMNNy9+8Y2G=xl=_J>f`ar;iZ$VQ$1JX2f z8?dD}g$LatHs%G6H^30}j0fk1CT22A?}#_|_$={c6EF98$vN_rb4Ckp?Pux{o;IJs zryRM)sV=0cf|37C)!@>^jKv*w^obTw*~sA7X=m{`JB|?~26b~9Emq-4YTZYfTB}KB zF|6GPVn^HU*D2ogcheGMA$;ufd?Ie002@pwrmFyXZC|rNO=fxu21S@8X)9ONw7ELO z1)39SZLJ(pttDb!LWN5W@*H?D~pM}Seu)_Gh6rPV#i3UOrVBb zXkvz``#{0iL)=-Cs9pWYcB+zmQ{;nMJmwb98OPKoIX1{Q#5J%Icn33#6H`|0)@gmh zu~g9>o<73c_>QOd3rAVwbC5&-*q-(-{UJJtXd{X81QMi4D=UjKhs-#Ac!plstKQll f%c<*MSrS=Z2)*S;{$(C*ROD2egtC^0y`}#G9(nWOC5&itKao+ z|6E|~Z&DT?56T_1>N+~fBp{)vbK8Emm$_!{4^ zo-qEShd*x_fBoTutsXbQW;rNyMstggfN}?|x`8fdF_$bBl1uT7#h$~CeHq9QdLUae z!Whc7>|kuk3)rt~I-99}dT&t3TxEpUJS3AR>uA=Kn%690eTJS7s28^PZ13v;`|=Y3 zdnnl!dm%Oy$EUrP37(Xxk|rwm^Wwpv(k9B%QGQRABNO(wvQp(H+_9tb@r7w+W2N#! zQxvLvxT9LIzF_JihJSxpzq$Qmm8)udPo;Xiy?K;9P1R^qmAiSSt8FXn>E!OWpWYqo za+K<$?6^2es&qeB+us!ZL6L8txqN;9$V5ppCAuymO8r^0X<#kTW;S}z!fA_Esz;cO zW{4(iY}%$7!i2Ts*Y^yz)LEE&n8UwalTSfZkR~ooYNx9 z6%qt>GpHIkq`P$pOj-|JZP$o z4|{=H!Vq_Wth7ytIKqxrGQmD&NPJ0yIH?{S=Jy?=h%}Zt>Jn`p?SSdD+cLE3BXo>+ zd515Hkgtd?kHkf>%&+kkXQdf_jsea08IikrC|8KOmI1dR^w|XGKc#cCET9oh95Qv2 zM$)fhHlbCX-efZMl7s-=r3tWCH{O6LNGU3#rKj11H5}GK?XQ1>NNn*xM#Kdc?&O&pr`fppW zkTqzml3zJP2y4%xf}Yh&Cu?udw=(vSjUBS~=k|ceN-Ge^aJL1bzO2PGax|^|Q@l4$ zws<5rcyrm}k?imwo#MT*c)m@ypuv02tH-s~2yw2>G0!wYoog1?$qn*zt{z+Lz+#6B z*sp4<&9O;4!=7t%Y|!_MwMVXra)Vr9vi&jw;V(>Y_i{gWbg#7sOg72cslZ%=C*d#zkiA`o?5>{r5kIzeukC#L;g9l;;M8Z## lYw}-a69Hb37GV$p)+{;MhDDK!56I_WW==j3H9CftG`VX&O|yq1|ek(ZZ?0SMldlx*Z)#0UT}{skle delta 20 acmZ3>yq1|ek(ZZ?0SGQnNZ!c3h!FrWq6HQJ diff --git a/__pycache__/Constants.cpython-39.pyc b/__pycache__/Constants.cpython-39.pyc index 467665c4206ea82f4195f78506c61f6075a3d002..4e4f281d555523e7b7bbfe2151106e6375a0ed7c 100644 GIT binary patch delta 20 acmZ3;vXF&4k(ZZ?0SMldlx*Y{V*&s#Lj;2W delta 20 acmZ3;vXF&4k(ZZ?0SGQnNZ!aT#smN^=LB^C diff --git a/main.py b/main.py index 2566a440..551c5ccf 100644 --- a/main.py +++ b/main.py @@ -20,6 +20,8 @@ def main(): run = False pygame.time.delay(200) + if(game.finalState()): + run = False game.move() game.update()