I made a display grid to test the A* (A-Star) algorithm written by Fanaticguru.
I don't know if it works on other PC but I wanted to share it with you.
Here is the display grid:
Code: Select all
; A* Pathfinding Display Grid - by Speedmaster
; topic: https://autohotkey.com/boards/viewtopic.php?f=6&t=43922
;
; autohotkey v.1.1.22 (32bit)
; ASTAR Pathfinder by FanaticGuru
; https://autohotkey.com/boards/viewtopic.php?p=185714#p185714
; Maze generator:
; https://rosettacode.org/wiki/Maze_solving#AutoHotkey
; ASCII Gaming functions by Speedmaster
; https://autohotkey.com/boards/viewtopic.php?f=19&t=43403
SetBatchLines, -1
SetControlDelay, -1
pico8:={black:"000000", dark_blue:"1D2B53", dark_purple:"7E2553", dark_green:"008751", brown:"AB5236", dark_gray:"5F574F", light_gray:"C2C3C7", white:"FFF1E8", red:"FF004D", orange:"FFA300", yellow:"FFEC27", green:"00E436", blue:"29ADFF", indigo:"83769C", pink:"FF77A8", peach:"FFCCAA"}
path_player:=[]
COLUMNS:=61
ROWS:=46
CELLWIDTH:=15
CELLHEIGHT:=15
VSPACING:="-1"
HSPACING:="-1"
GRIDFONTSIZE:=15
PLAYER:="2_2_2"
target:="2_60_44"
MAP_WIDTH:=COLUMNS
MAP_HEIGHT:=ROWS
;// Tile Types
TILE_ROCKFLOOR := 0
TILE_WALL := 1
;TILE_TYPE:={value[character, color, passable=true, tag name]}
TILE_TYPE:={ 0:[ "" ,pico8.dark_gray ,true , "Rock_floor" ]
,1:[ "g" ,pico8.brown ,false , "Wall" ] }
gui, font, s12
gui, add, text, x10 y10 h30 cwhite, Press F2 to call the A* Pathfinder (by FanaticGuru)
gui, add, text, xs yp25 h30 cwhite, Left click or use arrow keys to move the player ( @ ) - use right click to move the target ( T )
;// create the Playing area (grid 1)
gui, font, , webdings
putgridtext(10,70,COLUMNS,ROWS,CELLWIDTH,CELLHEIGHT,GRIDFONTSIZE,"green",VSPACING,HSPACING, "0x201 center -border")
;// create the Playing area (grid 2)
gui, font, bold, helvetica
putgridtext(10,70,COLUMNS,ROWS,CELLWIDTH,CELLHEIGHT,12,"green",VSPACING,HSPACING, "0x201 center -border")
gui, font, normal, helvetica
putgridtext(10,70,61,45,15,15,12,"green","-1","-1", "0x201 center hidden border")
;// add help text
gui, add, text, xs yp25 h30 cwhite, F1: Debug Map F2: Show Path F3: New Map F4: Clear Map F5: Chasing Mode F6:Show Grid F7: Save Map
gui, add, text, xs yp25 h30 cwhite, Crt+Left click : Add Wall Ctr+Right click : Remove Wall
gui, font, italic s10, consolas
gui, add, text, x750 yp25 h30 cyellow, by Speedmaster
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; create maze
;https://rosettacode.org/wiki/Maze_solving#AutoHotkey
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
oMaze := [] ; initialize
loop, 22
{
row := A_Index
loop, 15 ; create oMaze[row,column] borders
col := A_Index, oMaze[row,col] := "LRTB" ; i.e. oMaze[2,5] := LRTB (add all borders)
}
maze:=Generate_maze(22, 15, oMaze)
world:=maze2text(oMaze)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;// this function create a 2d array grid DataWorld:{} from a variable
AgLoadDataMap("world")
dataNodes:=[]
for i, j in dataworld
for k, l in j
{
if (TILE_TYPE[l].3)
{
dataNodes[i,k]:=0 ; (i=col k=row)
}
else
dataNodes[i,k]:=1 ; (i=col k=row)
}
;// Draw the world map
AgDrawDataMap(dataworld,1,"Drawtile")
gui, +resize
gui, color, black
gui, show,, A* Pathfinding Display Grid v1.0
;// Draw the Player on the grid
drawchar(player, "@", pico8.green)
;// draw the target
drawchar(target, "T", pico8.yellow)
;See wat type of tile is at current player position
lookdata() ; this function look to the datagrid dataworld
return
;left click on cell
clickcell:
if (click_debug)
msgbox, % a_guicontrol
if !(getKeyState("LCtrl", "P"))
if ispassable(agmove(a_guicontrol,"ex"),agmove(a_guicontrol,"ey"))
{
clearcell(player)
player:=agmove(a_guicontrol,"z",1)
drawchar(player,"@", pico8.green)
gosub, find_target
}
if (getKeyState("LCtrl", "P"))
{
drawtile(a_guicontrol,TILE_WALL)
Dataworld[draw2][draw3]:=TILE_WALL
dataNodes[draw2][draw3]:=TILE_WALL
}
return
; right click on cell
GuiContextMenu:
if chase
{
chase:=!chase
settimer, chaseme, off
}
if (click_debug)
msgbox, % a_guicontrol
if !(getKeyState("LCtrl", "P"))
if ispassable(agmove(a_guicontrol,"ex"),agmove(a_guicontrol,"ey"))
{
clearcell(target)
target:=agmove(a_guicontrol,"z",1)
drawchar(target, "T", "yellow")
gosub, find_target
}
if (getKeyState("LCtrl", "P"))
{
drawtile(a_guicontrol,Rock_floor)
Dataworld[draw2][draw3]:=TILE_ROCKFLOOR
dataNodes[draw2][draw3]:=TILE_ROCKFLOOR
}
return
up::
player:=agmove(player, "y", -1)
gosub, check_if_passable
return
down::
player:=agmove(player, "y", 1)
gosub, check_if_passable
return
left::
player:=agmove(player, "x", -1)
gosub, check_if_passable
return
right::
player:=agmove(player, "x", 1)
gosub, check_if_passable
return
check_if_passable:
if ispassable(nx, ny) ; nx= new pos x ; ny= new pos y
{
;Draw the previously saved tile value to the previous position
drawtile(previous,TILE_EMPTY)
;// Draw the player to the new position
drawchar(player,"@", pico8.green)
lookdata() ; update currenttilevalue variable
}
else
{
;// Don't move the player >> restore previous player postition
player:=previous
}
return
IsPassable(npX, npy) ; npx =new pos x , npy =new pos y
{
global
;// Store the value of the tile specified
tilevalue:= DataWorld[npX][npy] ;npx = new pos x npy = new pos y
;// Before we do anything, make sure that the coordinates are valid
if % (npX < 1 || npX > MAP_WIDTH || npy < 1 || npy > MAP_HEIGHT)
return false
;// Return true if it's passable
;if % ( TileValue == TILE_FLOOR || TileValue == TILE_WATER || TileValue == TILE_OPENDOOR )
if Tile_type[TileValue].3
return true
;// If execution get's here, it's not passable
return False
}
DrawTile( cellvar, TILE_Value)
{
global
drawchar(cellvar, TILE_TYPE[TILE_Value].1)
colorcell(cellvar, TILE_TYPE[TILE_Value].2)
}
lookdata() ; report wat there is at current player position in data grids
{
global
PlayerX:=agmove(player,"ex") ;ex= extract X position of player
PlayerY:=agmove(player,"ey") ;ey= extract Y poisiotn of player
currenttilevalue:= DataWorld[PlayerX][PlayerY]
}
Debugtile( cellvar, TILE_Value)
{
global
CellFont(cellvar, "s11", "arial")
drawchar(cellvar, TILE_Value)
colorcell(cellvar, TILE_TYPE[TILE_Value].2)
}
Restoretile( cellvar, TILE_Value)
{
global
CellFont(cellvar, "s11", "webdings")
drawchar(cellvar, TILE_TYPE[TILE_Value].1)
colorcell(cellvar, TILE_TYPE[TILE_Value].2)
}
F7::
; save map
FileSaveAs:
Gui +OwnDialogs ; Force the user to dismiss the FileSelectFile dialog before returning to the main window.
FileSelectFile, SelectedFileName, S16,, Save File, Text Documents (*.txt)
if SelectedFileName = ; No file selected.
return
CurrentFileName = %SelectedFileName%
Gosub SaveCurrentFile
return
SaveCurrentFile: ; Caller has ensured that CurrentFileName is not blank.
IfExist %CurrentFileName%
{
FileDelete %CurrentFileName%
if ErrorLevel
{
MsgBox The attempt to overwrite "%CurrentFileName%" failed.
return
}
}
Lines := []
text_out := ""
For i, j In Dataworld
For k, l In j
{
Lines[j] .= l
}
For Each, Line In Lines
text_out .= Line . "`n"
FileAppend, %text_out%, %CurrentFileName% ; Save the contents to the file.
msgbox, map saved to %CurrentFileName%
return
f5::
;chasing mode
chase:=!chase
if chase
settimer, chaseme, 500
else
settimer, chaseme, off
return
chaseme:
start:=A_TickCount
path_chase_Monster:=StrSplit(AGPathfind(dataNodes, target, player), ",")
if path_chase_Monster.maxindex()>2
{
for i, j in path_chase_Monster
{
now := A_TickCount-start
;if j
if now > 8000
break
if !(chase)
break
sleep, 100
clearcell(target)
if (j!=path_chase_Monster[path_chase_Monster.maxindex()-1])
{
drawchar(j,"T", pico8.yellow)
target:=j
}
else
{
drawchar(j,"T", pico8.yellow)
target:=j
break
}
}
}
return
f1::
; debug map
debugmap:=!debugmap
if debugmap
AgDrawDataMap(dataworld,1,"DebugTile")
else
AgDrawDataMap(dataworld,1,"Restoretile")
return
f2::
;show the path
solve:=!solve
if chase
if solve
{
chase:=!chase
settimer, chaseme, off
}
find_target:
if !(solve)
{
for i, j in path_player
{
if (j!=player) && (j!=target)
drawchar(j," ")
}
path_player:=""
return
}
for i, j in path_player
{
if (j!=player) && (j!=target)
drawchar(j," ", pico8.pink)
}
path_player:=[]
path:=""
path:=AGPathfind(dataNodes, player, target)
path_player:=StrSplit(path, ",")
for i, j in path_player
if (j!=player) && (j!=target)
drawchar(j,"+", pico8.pink)
return
f3::
; draw a new map
if solve
solve:=!solve
drawchar(player, "")
drawchar(target, "")
PLAYER:="2_2_2"
target:="2_60_44"
;// Draw the Player on the grid
drawchar(player, "@", pico8.green)
;// draw the target
drawchar(target, "T", pico8.yellow)
for i, j in path_player
{
if (j!=player) && (j!=target)
drawchar(j," ", pico8.pink)
}
path_player:=""
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; create new maze
;https://rosettacode.org/wiki/Maze_solving#AutoHotkey
oMaze := [] ; initialize
loop, 22
{
row := A_Index
loop, 15 ; create oMaze[row,column] borders
col := A_Index, oMaze[row,col] := "LRTB" ; i.e. oMaze[2,5] := LRTB (add all borders)
}
maze:=Generate_maze(22, 15, oMaze)
world:=maze2text(oMaze)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
dataworld2:=ObjFullyClone(dataworld)
AgLoadDataMap("world")
dataNodes:=[] ; grid of closed and open nodes
for i, j in dataworld
for k, l in j
{
if (TILE_TYPE[l].3) ; if tiletype is false
{
dataNodes[i,k]:=0 ; (i=col k=row)
}
else ; if true
dataNodes[i,k]:=1 ; (i=col k=row)
}
;// Draw the world map
AgDrawDataMapb(dataworld,1,"Drawtile")
return
f9::
;debug click on cell
click_debug:=!click_debug
return
f4::
; clear the map
for i, j in dataworld ;i col k row
for k, l in j
{
if !(i=1) && !(k=1) && !(i=dataworld.maxindex()) && !(k=45)
{
drawtile("1_" i "_" k,Rock_floor)
Dataworld[i][k]:=TILE_ROCKFLOOR
dataNodes[i][k]:=TILE_ROCKFLOOR
}
}
return
f6::
showborders:=!showborders
if (showborders)
{
gridshow(3)
gridshowborders(3)
}
else
gridhideborders(3)
return
ObjFullyClone(obj)
{
nobj := obj.Clone()
for k,v in nobj
if IsObject(v)
nobj[k] := A_ThisFunc.(v)
return nobj
}
guiclose:
esc::
exitapp
return
;Maze generator functions
;https://rosettacode.org/wiki/Maze_solving#AutoHotkey
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
maze2text(oMaze){
width := oMaze.1.MaxIndex()
BLK := "¦"
for row, objRow in oMaze
{
for col, val in objRow ; add ceiling
{
ceiling := InStr(oMaze[row, col] , "1") && InStr(oMaze[row-1, col] , "1") ? "10" BLK "0" : "1000"
grid .= (InStr(val, "T") ? "1111" : ceiling) (col = Width ? "1`n" : "")
}
for col, val in objRow ; add left wall
{
wall := SubStr(val, 0) = "1" ? BLK : "0"
grid .= (InStr(val, "L") ? "10" : "00") wall "0" (col = Width ? "1`n" : "") ; add left wall if needed then outer right border
}
}
Loop % Width
Grid .= "1111" ; add bottom floor
Grid .= "1" ; add right bottom corner
return RegExReplace(grid , BLK " (?=" BLK ")" , BLK BLK BLK BLK) ; fill gaps
}
Generate_maze(row, col, oMaze) {
neighbors := row+1 "," col "`n" row-1 "," col "`n" row "," col+1 "`n" row "," col-1
Sort, neighbors, random ; randomize neighbors list
Loop, parse, neighbors, `n ; for each neighbor
{
rowX := StrSplit(A_LoopField, ",").1 ; this neighbor row
colX := StrSplit(A_LoopField, ",").2 ; this neighbor column
if !instr(oMaze[rowX,colX], "LRTB") || !oMaze[rowX, colX] ; if visited (has a missing border) or out of bounds
continue ; skip
; remove borders
if (row > rowX) ; Cell is below this neighbor
oMaze[row,col] := StrReplace(oMaze[row,col], "T") , oMaze[rowX,colX] := StrReplace(oMaze[rowX,colX], "B")
else if (row < rowX) ; Cell is above this neighbor
oMaze[row,col] := StrReplace(oMaze[row,col], "B") , oMaze[rowX,colX] := StrReplace(oMaze[rowX,colX], "T")
else if (col > colX) ; Cell is right of this neighbor
oMaze[row,col] := StrReplace(oMaze[row,col], "L") , oMaze[rowX,colX] := StrReplace(oMaze[rowX,colX], "R")
else if (col < colX) ; Cell is left of this neighbor
oMaze[row,col] := StrReplace(oMaze[row,col], "R") , oMaze[rowX,colX] := StrReplace(oMaze[rowX,colX], "L")
Generate_maze(rowX, colX, oMaze) ; recurse for this neighbor
}
return, oMaze
}
; Astar_Grid and supporting functions by FanaticGuru
;topic: https://autohotkey.com//boards/viewtopic.php?p=185714#p185714
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Astar_Grid(X1, Y1, X2, Y2, closed)
{
if !IsObject(Closed)
Closed := {}
Open := {}, From := {}, G := {}, F := {}
Open[X1, Y1] := true, G[X1, Y1] := 0
F[X1, Y1] := Estimate_F(X1, Y1, X2, Y2)
while Open.MaxIndex()
{
Lowest_F_Set(X, Y, F, Open)
if (X = X2 and Y = Y2)
return From_Path(From, X, Y)
Open[X].Delete(Y)
if !Open[X].MaxIndex()
Open.Delete(X)
Closed[X, Y] := true
for index, Near in [{"X": X, "Y": Y-1},{"X": X-1, "Y": Y},{"X": X+1, "Y": Y},{"X": X, "Y": Y+1}]
{
if (Closed[Near.X, Near.Y] = true)
continue
Open[Near.X, Near.Y] := true, tG := G[X, Y] + 1
if (IsObject(G[Near.X, Near.Y]) and tG >= G[Near.X, Near.Y])
continue
From[Near.X, Near.Y] := {"X": X, "Y": Y}
G[Near.X, Near.Y] := tG
F[Near.X, Near.Y] := G[Near.X, Near.Y] + Estimate_F(Near.X, Near.Y, X2, Y2)
}
}
}
Estimate_F(X1, Y1, X2, Y2)
{
return Abs(X1-X2) + Abs(Y1-Y2)
}
Lowest_F_Set(ByRef X, ByRef Y, ByRef F, ByRef Set)
{
l := 0x7FFFFFFF
for tX , element in Set
for tY, val in element
if (F[tX, tY] < l)
l := F[tX, tY], X := tX, Y := tY
return l
}
From_Path(From, X, Y)
{
Path := {}, pb := [], XY := {"X": X, "Y": Y}
Path.InsertAt(1, XY)
while (IsObject(From[XY.X, XY.Y]))
Path.InsertAt(1, XY:= From[XY.X, XY.Y])
return Path
}
;ASCII Gaming functions by Speedmaster
;https://autohotkey.com/boards/viewtopic.php?f=19&t=43403
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
AgDrawDataMapb(datagrid, gridnumber:="", function_name:="", Bypass_Values_List:="")
{
global
For Col, Rows In datagrid
For Row, value In Rows
{
if (gridnumber)
cell_to_draw=%gridnumber%_%col%_%row%
else
cell_to_draw=%col%_%row%
if value not in %Bypass_Values_List%
if (dataworld[col][row]!=dataworld2[col][row])
%function_name%(cell_to_draw, value)
}
}
AGPathfind(Datagrid, StartCell:="", TargetCell:="")
{
Closed := {}
for i, j in Datagrid
for k, l in j
{
if (l = "1")
Closed[i,k]:= true
}
stringsplit, sta, StartCell, _
stringsplit, targ, TargetCell, _
For Key, Node In Astar_Grid(sta2, sta3, targ2, targ3, Closed)
pb .= sta1 . "_" . node.X "_" node.y ","
stringtrimright,pb,pb, 1
return pb
}
PutGridText(GridPosX="10",GridPosY=10, number_of_columns=3, number_of_raws=3, width_of_cell=100, height_of_cell=100,fontsize:=18,fontcolor:="red", XCellSpacing=0, YCellSpacing=0, options="center 0x200", fill:=" ")
{
; create a grid with borders
global
if gridnumber=
GridNumber:=0
GridNumber:=GridNumber+1
MaxCols_Grid%GridNumber%:=number_of_columns
MaxRows_Grid%GridNumber%:=number_of_raws
gui, font, s%fontsize%
gui, add, text, hidden w0 h0 x%GridPosX% y%GridPosY% section
Row:=0 Col:=0
loop, %number_of_raws% {
Row:= ROw+1
loop, %number_of_columns% {
Col:= Col+1
if Col=1
gui, add, text, section %options% c%fontcolor% 0x200 BackGroundTrans border hidden0 w%width_of_cell% h%height_of_cell% xs y+%YCellSpacing% v%GridNumber%_%Col%_%Row% gclickcell, %fill%
else
gui, add, text, %options% c%fontcolor% 0x200 BackGroundTrans border hidden0 w%width_of_cell% h%height_of_cell% x+%XCellSpacing% ys v%GridNumber%_%Col%_%Row% gclickcell, %fill%
}
Col:=0
}
}
AgLoadDataMap(InputGridMap:="Walls", colsep:="", cols:="maxcols_grid1", rows:="maxrows_grid1")
{
global
;create a col major data grid (create a real 2d data matrix)
data%InputGridMap%:=[]
Loop, Parse, %InputGridMap%, `n
{
Row := A_Index
Loop, Parse, A_LoopField, %colsep% , %A_Space%%A_Tab%
{
Col := A_Index
Data%InputGridMap%[Col,Row] := A_LoopField
}
}
}
AgDrawDataMap(datagrid, gridnumber:=1, function_name:="", Bypass_Values_List:="")
{
global
For Col, Rows In datagrid
For Row, value In Rows
{
cell_to_draw=%gridnumber%_%col%_%row%
if value is xdigit
if value not in %Bypass_Values_List%
%function_name%(cell_to_draw, value)
}
}
drawchar(varname, chartodraw:="@", color:="")
{
global
stringsplit, draw, varname, _
out:= draw1 . "_" . draw2 . "_" . draw3
guicontrol,, %out%, %chartodraw%
colorcell(out, color)
}
ClearCell(parameters)
{
DrawChar(parameters, " ")
}
ColorCell(cell_to_paint, color:="red")
{
GuiControl, +c%color% , %cell_to_paint%
GuiControl, hide , %cell_to_paint%
GuiControl, show , %cell_to_paint%
}
CellFont(cell, params:="", fontname:="")
{
Gui, Font, %params%, %fontname%
GuiControl, font , %cell%
GuiControl, hide , %cell%
GuiControl, show , %cell%
}
GridShow(gridnumber="1")
{
global
Row:=0 Col:=0
loop, % MaxRows_Grid%gridnumber% {
Row:= ROw+1
loop, % MaxCols_Grid%gridnumber% {
Col:= Col+1
guicontrol, hide0, %GridNumber%_%Col%_%Row%
}
Col:=0
}
}
GridshowBorders(gridnum="1")
{
global
Row:=0 Col:=0
loop, % MaxRows_Grid%gridnum% {
Row:= ROw+1
loop, % MaxCols_Grid%gridnum% {
Col:= Col+1
guicontrol, +border, %gridnum%_%Col%_%Row%
}
Col:=0
}
gui, color,
}
GridHideBorders(gridnum="1")
{
global
Row:=0 Col:=0
loop, % MaxRows_Grid%gridnum% {
Row:= ROw+1
loop, % MaxCols_Grid%gridnum% {
Col:= Col+1
guicontrol, -border, %GridNum%_%Col%_%Row%
}
Col:=0
}
gui, color,
}
AGMove(Varname,axes,value1:=1,value2:=1,value3:=1)
{
global
; Increment Cell variable name in the grid for ex. if you are on cell 1_1_1 to go to the cell "1_2_1" do AGMove("1_1_1", "x", 1)
; for ex. if you are on cell 1_1_1 (=grid1 col1 row1) to jump to 2_1_3 (=grid2 col1 row3) do AGMove("1_1_1", "zxy", 1,0,2)
; for ex. if you are on cell 1_1_1 to go to cell 1_2_2 do AGMove("1_1_1", "xy", 1,1)
;Call the main function AGM()
AGM(varname,value1,value2,value3)
StringSplit, ar, varname , _
;increment the grid number only
if axes = z
{
nz:=value1+ar1
ny:=ar3
nx:=ar2
}
;increment column only
if axes = x
{
nz:=ar1
nx:=value1+ar2
ny:=ar3
}
; increment row only
if axes = y
{
nz:=ar1
nx:=ar2
ny:=value1+ar3
}
; increment column and row (add value1 to column and value2 to row)
if axes = xy
{
nz:=ar1
nx:=value1+ar2
ny:=value2+ar3
}
; select a grid and increment column and row
if axes = zxy
{
nz:=value1+ar1
nx:=value2+ar2
ny:=value3+ar3
}
;EZ = extract Z (return the grid number)
if axes = EZ
return ar1
;EX = extract x (return the column number)
if axes = EX
return ar2
;EY = extract y (return the row number)
if axes = EY
return ar3
;SX = set x (set the colum number)
if axes = SX
{
nz:=ar1
nx:=value1
ny:=ar3
return % nz . "_" . nX . "_" . nY
}
;SY = set y (set the row number)
if axes = SY
{
nz:=ar1
nx:=ar2
ny:=value1
return % nz . "_" . nX . "_" . nY
}
;SZ = set Z (set the Grid number)
if axes = SZ
{
nz:=value1
nx:=ar2
ny:=ar3
return % nz . "_" . nX . "_" . nY
}
return % nz . "_" . nX . "_" . nY
}
;AGM is ASCII GAMING MAIN FUNCTION
AGM(varname,NewZ:="1",NewX:="0", NewY:="0")
{
global Previous, nx, ny, nz
nx:=0
ny:=0
nz:=NewZ
previous:=varname
StringSplit, ar, varname , _
nx:=newX+ar2
ny:=newY+ar3
return % nz . "_" . nX . "_" . nY
}
Crt+Left click : Add a wall
Ctr+Right click : Remove a wall
F1: Debug Map
F2: Show the path
F3: New Map
F4: Clear Map
F5: Chasing Mode : the target will chase the player
F6: Show Grid
F7: Save Map
f9: Debug click
Any suggestion on how to improve the code are welcome.
Most of the functions are recycled from my previous ASCII game:
https://autohotkey.com/boards/viewtopic ... 19&t=43403
You can find the pathfinder algorithm (by FanaticGuru) here:
topic: https://autohotkey.com/boards/viewtopic ... ca#p185714
I also used a map generator found here:
https://rosettacode.org/wiki/Maze_solving#AutoHotkey
Other A* pathfinding related topics
https://autohotkey.com/board/topic/3616 ... ng-editor/
https://autohotkey.com/board/topic/7761 ... ng-with-a/
https://autohotkey.com/board/topic/4902 ... m-in-grid/
https://autohotkey.com/board/topic/1470 ... ple-nodes/