pos AS Coord
' Coordinates of position on map parent
AS Coord
' Coordinates of previous position on path f
AS INTEGER ' F = G + H (total movement cost) status
AS INTEGER ' 0 for unsearched, 1 for open, 2 for closed (explored)
DIM Start
AS Coord
, Target
AS Coord
CONST RandomSearch
= 1 ' 1 => Randomly decide intesnity of search estimations (rush) CONST DEBUG
= 50 ' 0 => Debug mode off '''''''''''''''''' DEBUG > 0 => Debug mode on, where DEBUG is animation speed
'''''''''''''''''' -1 => Debug mode on with SLEEPs between frames
CONST Resx
= 1024 ' Set Screen Resolution CONST Resy
= 768 ' If you change it, the map will automatically fill the screen CONST FPS
= 20 ' Animation Speed CONST TileSize
= 10 ' Set size of square tiles CONST MinMapDensity
= 10 ' Set range of density to fill generated maps with walls CONST MinWallLength
= MinMapDensity
/ 2 CONST MaxWallLength
= MaxMapDensity
/ 2
Mapx
= INT((Resx
* .95) / TileSize
) ' Dimension SampleMap to fit to screenMapy
= INT((Resy
* .95) / TileSize
)DIM SampleMap
(Mapx
, Mapy
)
MaxPathLength = Mapx * Mapy * 0.5 ' Max number of saved path positions
DIM Path
(MaxPathLength
) AS Coord
'' Dimension array of path coords to be filled in later
REDIM Path
(MaxPathLength
) AS Coord
, SampleMap
(Mapx
, Mapy
)
SampleMap(ix, 0) = 1: SampleMap(ix, Mapy) = 1
SampleMap(0, iy) = 1: SampleMap(Mapx, iy) = 1
MapDensity
= INT((MaxMapDensity
- MinMapDensity
) * RND) + MinMapDensity
RandNumber
= INT(100 * RND) + 1 IF RandNumber
< MapDensity
THEN SampleMap
(ix
, iy
) = 1
FOR i
= 0 TO (MapDensity
* 2) WallDirection
= INT(2 * RND) + 1 WallLength
= INT((MaxWallLength
- MinWallLength
) * RND) + MinWallLength
IF WallX
+ WallLength
> Mapx
THEN WallX
= Mapx
- WallLength
FOR ix
= WallX
TO (WallX
+ WallLength
) SampleMap(ix, iy) = 1
IF WallY
+ WallLength
> Mapy
THEN WallY
= Mapy
- WallLength
FOR iy
= WallY
TO (WallY
+ WallLength
) SampleMap(ix, iy) = 1
Start.x
= INT((Mapx
- 2) * RND) + 2 ' Set start position Start.y
= INT((Mapy
- 2) * RND) + 2 Target.x
= INT((Mapx
- 2) * RND) + 2 ' Set target position Target.y
= INT((Mapy
- 2) * RND) + 2
CALL SetPath
(Path
(), Start
, Target
, SampleMap
())
i = 0
IF SampleMap
(ix
, iy
) = 1 THEN CALL DrawBlock
(ix
, iy
, 15)
i = i + 1
CALL DrawBlock
(Path
(i
).x
, Path
(i
).y
, 10) CALL DrawBlock
(Target.x
, Target.y
, 4)
i = 0
TargetFound = 0
SUB SetPath
(Path
() AS Coord
, StartPos
AS Coord
, TargetPos
AS Coord
, Map
())
DIM PathMap
(Mapx
, Mapy
) AS PathCoord
PathMap
(ix
, iy
).
pos.x
= ix
PathMap
(ix
, iy
).
pos.y
= iy
DIM Cpos
AS Coord: Cpos
= StartPos
DIM SearchPathSet
(4) AS PathCoord
, OpenPathSet
(MaxPathLength
) AS PathCoord
PathMap(Cpos.x, Cpos.y).status = 2
count = count + 1
IF PathMap
(TargetPos.x
, TargetPos.y
).status
= 2 THEN TargetFound
= 1:
EXIT DO
SearchPathSet(0) = PathMap(Cpos.x, Cpos.y)
SearchPathSet(1) = PathMap(Cpos.x + 1, Cpos.y)
SearchPathSet(2) = PathMap(Cpos.x - 1, Cpos.y)
SearchPathSet(3) = PathMap(Cpos.x, Cpos.y + 1)
SearchPathSet(4) = PathMap(Cpos.x, Cpos.y - 1)
IF Collision
(SearchPathSet
(i
).
pos, Map
()) <> 1 THEN
IF SearchPathSet
(i
).status
= 1 THEN NewG = PathGCost(SearchPathSet(0).g)
IF NewG
< SearchPathSet
(i
).g
THEN SearchPathSet
(i
).g
= NewG
IF SearchPathSet
(i
).status
= 0 THEN SearchPathSet
(i
).parent
= SearchPathSet
(0).
pos SearchPathSet(i).status = 1
SearchPathSet(i).g = PathGCost(SearchPathSet(0).g)
SearchPathSet(i).h = PathHCost(SearchPathSet(i), TargetPos)
SearchPathSet(i).f = SearchPathSet(i).g + SearchPathSet(i).h
OpenPathSet(OpenPathCount) = SearchPathSet(i)
OpenPathCount = OpenPathCount + 1
PathMap(Cpos.x + 1, Cpos.y) = SearchPathSet(1)
PathMap(Cpos.x - 1, Cpos.y) = SearchPathSet(2)
PathMap(Cpos.x, Cpos.y + 1) = SearchPathSet(3)
PathMap(Cpos.x, Cpos.y - 1) = SearchPathSet(4)
LowF = 32000: ixOptimal = 0: iyOptimal = 0
FOR i
= 0 TO OpenPathCount
IF OpenPathSet
(i
).status
= 1 AND OpenPathSet
(i
).f
<> 0 THEN IF OpenPathSet
(i
).f
< LowF
THEN LowF = OpenPathSet(i).f
ixOptimal
= OpenPathSet
(i
).
pos.x
iyOptimal
= OpenPathSet
(i
).
pos.y
OptimalPath_i = i
Cpos
= PathMap
(ixOptimal
, iyOptimal
).
pos OpenPathSet(OptimalPath_i).status = 2
IF Map
(ix
, iy
) = 1 THEN CALL DrawBlock
(ix
, iy
, 15) CALL DrawBlock
(TargetPos.x
, TargetPos.y
, 4) IF PathMap
(ix
, iy
).status
= 1 THEN CALL DrawBlock
(ix
, iy
, 3) IF PathMap
(ix
, iy
).status
= 2 THEN CALL DrawBlock
(ix
, iy
, 10)
DIM backpath
(MaxPathLength
) AS PathCoord
backpath
(0).
pos = PathMap
(TargetPos.x
, TargetPos.y
).
pos
backpath
(i
).
pos = PathMap
(backpath
(i
- 1).
pos.x
, backpath
(i
- 1).
pos.y
).parent
pathlength = i: startreached = 1
i = 0: startreached = 0
IF startreached
= 1 THEN i
= i
+ 1: Path
(i
) = backpath
(iback
).
pos Path
(i
) = backpath
(iback
).
pos startreached = 1
PathGCost = ParentG + 10
FUNCTION PathHCost
(TilePath
AS PathCoord
, TargetPos
AS Coord
) dx
= ABS(TilePath.
pos.x
- TargetPos.x
)dy
= ABS(TilePath.
pos.y
- TargetPos.y
)distance
= SQR((TargetPos.x
- TilePath.
pos.x
) ^ 2 + (TargetPos.y
- TilePath.
pos.y
) ^ 2)PathHCost = ((SearchIntensity / 20) + 10) * (dx + dy + ((SearchIntensity / 10) * distance))
IF Map
(Position.x
, Position.y
) <> 0 THEN c
= 1 Collision = c
SUB DrawBlock
(x
, y
, blockcolor
) x0 = ((x * TileSize) - (TileSize / 2)) + TileSize + 20
y0 = ((y * TileSize) - (TileSize / 2)) + TileSize
x1 = ((x * TileSize) + (TileSize / 2)) + TileSize + 20
y1 = ((y * TileSize) + (TileSize / 2)) + TileSize
LINE (x0
, y0
)-(x1
, y1
), blockcolor
, BF