// TMW2 Scripts
// Author:
// Jesusalva
// Description:
// Maze generation script (Protip: (30,30) is ALWAYS reachable - for @warp)
// Based on https://wiki.themanaworld.org/index.php/Archive:Afterlife#maze_generation
// Begin script, instance is required. Maze is Saved to player data.
// Scopes: MAZE_ {ID, MX, MY} or {X_Y$} or {X_Y_ALLOWEDTYPES} or {X_Y_ID}
/////////////////////////////////////////////////////////////////////////////////
// MazeVar(x,y,param)
function script MazeVar {
return "MAZE_"+getarg(0)+"_"+getarg(1)+getarg(2, "");
}
/////////////////////////////////////////////////////////////////////////////////
// WarpToMaze(instanceID, x, y)
function script WarpToMaze {
end;
}
/////////////////////////////////////////////////////////////////////////////////
// SetMazeCon(Maze, north, west, east, south)
function script SetMazeCon {
setd(getarg(0)+"$["+MAZENORTH+"]", getarg(1));
setd(getarg(0)+"$["+MAZE_WEST+"]", getarg(2));
setd(getarg(0)+"$["+MAZE_EAST+"]", getarg(3));
setd(getarg(0)+"$["+MAZESOUTH+"]", getarg(4));
return;
}
/////////////////////////////////////////////////////////////////////////////////
// UpdateMazeCon(Maze, x, y)
function script UpdateMazeCon {
if (getd(getarg(0)+"$["+MAZENORTH+"]") != "WALL")
setd(getarg(0)+"$["+MAZENORTH+"]", str(getarg(1))+"_"+str(getarg(2)-1));
if (getd(getarg(0)+"$["+MAZE_WEST+"]") != "WALL")
setd(getarg(0)+"$["+MAZE_WEST+"]", str(getarg(1)-1)+"_"+str(getarg(2)));
if (getd(getarg(0)+"$["+MAZE_EAST+"]") != "WALL")
setd(getarg(0)+"$["+MAZE_EAST+"]", str(getarg(1)+1)+"_"+str(getarg(2)));
if (getd(getarg(0)+"$["+MAZESOUTH+"]") != "WALL")
setd(getarg(0)+"$["+MAZESOUTH+"]", str(getarg(1))+"_"+str(getarg(2)+1));
return;
}
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// ParseMaze(mapType, x, y)
function script ParseMaze {
.@t=getarg(0);
.@x=getarg(1);
.@y=getarg(2);
/*
// Prepare .@sim, the simulator array
copyarray(.@sim,
getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")),
getarraysize(getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES"))));
*/
// Setup the maze connectors
.@v$=MazeVar(.@x, .@y);
switch (.@t) {
case MAZEMAPTYPE_NULL:
SetMazeCon(.@v$, "WALL", "WALL", "WALL", "WALL");
// It's a fallback
Exception("ERROR IN PARSER, FALLBACK", RB_DEBUGMES|RB_ISFATAL);
return true;
break;
// N W E S
case MAZEMAPTYPE_DEADS:
SetMazeCon(.@v$, "WALL", "WALL", "WALL", "");
break;
case MAZEMAPTYPE_DEADW:
SetMazeCon(.@v$, "WALL", "", "WALL", "WALL");
break;
case MAZEMAPTYPE_DEADN:
SetMazeCon(.@v$, "", "WALL", "WALL", "WALL");
break;
case MAZEMAPTYPE_DEADE:
SetMazeCon(.@v$, "WALL", "WALL", "", "WALL");
break;
// N W E S
case MAZEMAPTYPE_CURVENW:
SetMazeCon(.@v$, "", "", "WALL", "WALL");
break;
case MAZEMAPTYPE_CURVENE:
SetMazeCon(.@v$, "", "WALL", "", "WALL");
break;
case MAZEMAPTYPE_CURVESW:
SetMazeCon(.@v$, "WALL", "", "WALL", "");
break;
case MAZEMAPTYPE_CURVESE:
SetMazeCon(.@v$, "WALL", "WALL", "", "");
break;
// N W E S
case MAZEMAPTYPE_TNWS:
SetMazeCon(.@v$, "", "", "WALL", "");
break;
case MAZEMAPTYPE_TNES:
SetMazeCon(.@v$, "", "WALL", "", "");
break;
case MAZEMAPTYPE_TWEN:
SetMazeCon(.@v$, "", "", "", "WALL");
break;
case MAZEMAPTYPE_TWES:
SetMazeCon(.@v$, "WALL", "", "", "");
break;
// N W E S
case MAZEMAPTYPE_LINENS:
SetMazeCon(.@v$, "", "WALL", "WALL", "");
break;
case MAZEMAPTYPE_LINEWE:
SetMazeCon(.@v$, "WALL", "", "", "WALL");
break;
// N W E S
case MAZEMAPTYPE_CROSS:
SetMazeCon(.@v$, "", "", "", "");
break;
}
// Now that connectors are set, we do simulations
/*
debugmes "(%d, %d) found %s (ID %d)", .@x, .@y, getd(MazeVar(.@x, .@y, "$["+MAZENORTH+"]")), getd(MazeVar(.@x, .@y, "_ID"));
debugmes "(%d, %d) is with north %s (ID %d)", .@x, .@y, getd(MazeVar(.@x, .@y, "$["+MAZENORTH+"]")), getd(MazeVar(.@x, .@y, "_ID"));
debugmes ".@v$ is %s", .@v$;
debugmes ".@v$[NORTH] is %s", getd(.@v$+"$["+MAZENORTH+"]");
*/
//////////////////////////
// Way north
if (getd(.@v$+"$["+MAZENORTH+"]") != "WALL") {
// Does north map accept this?
//debugmes "(%d, %d) is worth proccessing in NORTH", .@x, .@y;
// Case 1: We're in the edge
if (.@y == 0)
return false;
// Case 2: South direction thinks it is a wall
if (getd(MazeVar(.@x, .@y-1, "$["+MAZESOUTH+"]")) == "WALL")
return false;
//debugmes "(%d, %d) found %s (ID %d)", .@x, .@y, getd(MazeVar(.@x, .@y-1, "$["+MAZESOUTH+"]")), getd(MazeVar(.@x, .@y-1, "_ID"));
// Okay, this is a valid movement, we continue
} else {
// Case 1: We're in the edge
if (.@y != 0) {
// Case 2: South direction thinks it is a wall
if (getd(MazeVar(.@x, .@y-1, "$["+MAZESOUTH+"]")) != "WALL")
return false;
}
}
//////////////////////////
// Way west
if (getd(.@v$+"$["+MAZE_WEST+"]") != "WALL") {
// Does west map accept this?
// Case 1: We're in the edge
if (.@x == 0)
return false;
// Case 2: West direction thinks it is a wall
if (getd(MazeVar(.@x-1, .@y, "$["+MAZE_EAST+"]")) == "WALL")
return false;
// Okay, this is a valid movement, we continue
} else {
// Case 1: We're in the edge
if (.@x != 0) {
// Case 2: West direction thinks it is a wall
if (getd(MazeVar(.@x-1, .@y, "$["+MAZE_EAST+"]")) != "WALL")
return false;
}
}
//////////////////////////
// Way down
if (getd(.@v$+"$["+MAZESOUTH+"]") != "WALL") {
// Can we do this?
// Case 1: We're in the edge
if (.@y == MAZE_MY)
return false;
// Case 2: Down direction is invalid?
// TODO
// Okay, this is a valid movement, we continue
}
//////////////////////////
// Way east
if (getd(.@v$+"$["+MAZE_EAST+"]") != "WALL") {
// Can we do this?
// Case 1: We're in the edge
if (.@x == MAZE_MX)
return false;
// Case 2: Right direction is invalid?
// TODO
// Okay, this is a valid movement, we continue
}
// All checks passed!
UpdateMazeCon(.@v$, .@x, .@y);
return true;
}
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// GenerateMaze(width, height, instanceID)
function script GenerateMaze {
// Save maze configuration
MAZE_ID=getarg(2);
MAZE_MX=getarg(0);
MAZE_MY=getarg(1);
freeloop(true);
// Delete previous maze data as relevant
debugmes "[STATUS] Clean up";
for (.@y=0; .@y < MAZE_MY; .@y++) {
for (.@x=0; .@x < MAZE_MX; .@x++) {
setd(MazeVar(.@x, .@y, "_ID"), 0);
deletearray(getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")));
deletearray(getd(MazeVar(.@x, .@y, "$")));
}
}
////////////////////
// SETUP
.@x=0; .@y=0;
debugmes "[STATUS] Setup";
// For every column:
while (.@x < MAZE_MX) {
// For every cell:
while (.@y < MAZE_MY) {
// Case 1: Left column
if (.@y == 0) {
// NW edge
if (.@x == 0)
setarray getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")),
MAZEMAPTYPE_DEADS, MAZEMAPTYPE_DEADE,
MAZEMAPTYPE_CURVESE;
// NE edge
else if (.@x == MAZE_MX)
setarray getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")),
MAZEMAPTYPE_DEADS, MAZEMAPTYPE_DEADW,
MAZEMAPTYPE_CURVESW;
// North wall
else
setarray getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")),
MAZEMAPTYPE_DEADS, MAZEMAPTYPE_DEADW, MAZEMAPTYPE_DEADE,
MAZEMAPTYPE_TWES, MAZEMAPTYPE_LINEWE,
MAZEMAPTYPE_CURVESE, MAZEMAPTYPE_CURVESW;
// Case 2: Right column
} else if (.@y == MAZE_MY) {
// SW edge
if (.@x == 0)
setarray getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")),
MAZEMAPTYPE_DEADN, MAZEMAPTYPE_DEADE,
MAZEMAPTYPE_CURVENE;
// SE edge
else if (.@x == MAZE_MX)
setarray getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")),
MAZEMAPTYPE_DEADN, MAZEMAPTYPE_DEADW,
MAZEMAPTYPE_CURVENW;
// South wall
else
setarray getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")),
MAZEMAPTYPE_DEADN, MAZEMAPTYPE_DEADW, MAZEMAPTYPE_DEADE,
MAZEMAPTYPE_TWEN, MAZEMAPTYPE_LINEWE,
MAZEMAPTYPE_CURVENE, MAZEMAPTYPE_CURVENW;
// Case 3: Nothing in special
} else {
setarray getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")),
MAZEMAPTYPE_DEADN, MAZEMAPTYPE_DEADW, MAZEMAPTYPE_DEADE, MAZEMAPTYPE_DEADS,
MAZEMAPTYPE_CURVENW, MAZEMAPTYPE_CURVENE, MAZEMAPTYPE_CURVESW, MAZEMAPTYPE_CURVESE,
MAZEMAPTYPE_TNWS, MAZEMAPTYPE_TNES, MAZEMAPTYPE_TWEN, MAZEMAPTYPE_TWES,
MAZEMAPTYPE_LINEWE, MAZEMAPTYPE_LINENS, MAZEMAPTYPE_CROSS;
}
// End the setup loop
.@y++;
}
.@x++;
.@y=0;
}
////////////////////
// BUILDING
.@x=0; .@y=0;
debugmes "[STATUS] Build";
// For every line:
while (.@y < MAZE_MY) {
// For every cell:
while (.@x < MAZE_MX) {
//debugmes "[STATUS] [BUILD %d %d] Running...", .@x, .@y;
// While connections weren't parsed
do {
// We start at (0,0) and go to (MAZE_MX,0)
// Then we go to (0,MAZE_MY) until (MAZE_MX,MAZE_MY)
// Shuffle the array
array_shuffle(getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")));
freeloop(true);
if (getarraysize(getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES"))))
.@mztype=array_pop(getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES")));
else
.@mztype=-1;
// XXX: MAZEMAPTYPE_NULL is also a bug
if (.@mztype <= 0) {
Exception("ERROR IN MAZE BUILDER ("+.@x+","+.@y+") MTYPEXY", RB_DEBUGMES|RB_IRCBROADCAST);
.@mztype=MAZEMAPTYPE_NULL;
}
setd(MazeVar(.@x, .@y, "_ID"), .@mztype);
// Attempt to parse connections
} while (!ParseMaze(.@mztype, .@x, .@y));
// End the build loop
.@x++;
}
.@y++;
.@x=0;
}
// Debug the statuses
.@x=0; .@y=0;
debugmes "[STATUS] Finishing...";
for (.@y=0; .@y < MAZE_MY; .@y++) {
.@l$="";
freeloop(true);
for (.@x=0; .@x < MAZE_MX; .@x++) {
//debugmes "[rpts] %d %d = %d", .@x, .@y, getd(MazeVar(.@x, .@y, "_ID"));
.@l$=.@l$+","+getd(MazeVar(.@x, .@y, "_ID"));
}
debugmes "[REPORT] %s", .@l$;
}
// Sanity Check
for (.@y=0; .@y < MAZE_MY; .@y++) {
for (.@x=0; .@x < MAZE_MX; .@x++) {
.@mid=getd(MazeVar(.@x, .@y, "_ID"));
.@v$=MazeVar(.@x, .@y);
.@n$=getd(.@v$+"$["+MAZENORTH+"]");
.@w$=getd(.@v$+"$["+MAZE_WEST+"]");
.@e$=getd(.@v$+"$["+MAZE_EAST+"]");
.@s$=getd(.@v$+"$["+MAZESOUTH+"]");
debugmes "\t%s\t\t\t", .@n$;
debugmes "%s|%s|%s", .@w$, .@s$, .@e$;
}
debugmes "%s (%d)", .@v$, .@mid;
}
freeloop(false);
debugmes "[STATUS] Finished";
end;
}
// One warp handler per maze map
maze0,30,30,0 script #MazeMaster NPC_MONA,{
/*
function mazeGen;
function parseConnections;
*/
//GenerateMaze(7, 7, 0);
GenerateMaze(5, 5, 0);
end;
}