// 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"); 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) 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 } ////////////////////////// // 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 } ////////////////////////// // 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) { freeloop(true); //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"))); .@maze_typexy=array_pop(getd(MazeVar(.@x, .@y, "_ALLOWEDTYPES"))); // XXX: MAZEMAPTYPE_NULL is also a bug if (.@maze_typexy <= 0) { Exception("ERROR IN MAZE BUILDER ("+.@x+","+.@y+") MTYPEXY"); .@maze_typexy=MAZEMAPTYPE_NULL; } setd(MazeVar(.@x, .@y, "_ID"), .@maze_typexy); // Attempt to parse connections } while (!ParseMaze(.@maze_typexy, .@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++) { freeloop(true); 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 "%s (%d): %s ", .@v$, .@mid, .@n$; //debugmes "%s | %s | %s", .@w$, .@s$, .@e$; } debugmes "[REPORT] %s", .@l$; } 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; }