Make /maze allocate 85.35543% less memory.

This commit is contained in:
UnknownShadow200 2016-03-22 11:25:06 +11:00
parent 2353897f3a
commit f983d09a7c
2 changed files with 153 additions and 174 deletions

View File

@ -33,27 +33,32 @@ namespace MCGalaxy.Commands
public override LevelPermission defaultRank { get { return LevelPermission.AdvBuilder; } } public override LevelPermission defaultRank { get { return LevelPermission.AdvBuilder; } }
public override void Use(Player p, string message) { public override void Use(Player p, string message) {
if (message.Length > 0 && !int.TryParse(message, out MazeDrawOp.randomizer)) { CatchPos cpos = default(CatchPos);
if (message.Length > 0 && !int.TryParse(message, out cpos.randomizer)) {
Help(p); return; Help(p); return;
} }
Player.SendMessage(p, "Place two blocks to determine the edges."); Player.SendMessage(p, "Place two blocks to determine the edges.");
p.ClearBlockchange(); p.ClearBlockchange();
p.blockchangeObject = cpos;
p.Blockchange += new Player.BlockchangeEventHandler(Blockchange1); p.Blockchange += new Player.BlockchangeEventHandler(Blockchange1);
} }
void Blockchange1(Player p, ushort x, ushort y, ushort z, byte type, byte extType) { void Blockchange1(Player p, ushort x, ushort y, ushort z, byte type, byte extType) {
RevertAndClearState(p, x, y, z); RevertAndClearState(p, x, y, z);
p.blockchangeObject = new Vector3U16(x, y, z); CatchPos cpos = (CatchPos)p.blockchangeObject;
cpos.x = x; cpos.y = y; cpos.z = z;
p.blockchangeObject = cpos;
p.Blockchange += new Player.BlockchangeEventHandler(Blockchange2); p.Blockchange += new Player.BlockchangeEventHandler(Blockchange2);
} }
void Blockchange2(Player p, ushort x, ushort y, ushort z, byte type, byte extType) { void Blockchange2(Player p, ushort x, ushort y, ushort z, byte type, byte extType) {
RevertAndClearState(p, x, y, z); RevertAndClearState(p, x, y, z);
Vector3U16 cpos = (Vector3U16)p.blockchangeObject; CatchPos cpos = (CatchPos)p.blockchangeObject;
DrawOp drawOp = new MazeDrawOp(); MazeDrawOp drawOp = new MazeDrawOp();
drawOp.randomizer = cpos.randomizer;
if (!DrawOp.DoDrawOp(drawOp, null, p, cpos.X, cpos.Y, cpos.Z, x, y, z)) if (!DrawOp.DoDrawOp(drawOp, null, p, cpos.x, cpos.y, cpos.z, x, y, z))
return; return;
if (p.staticCommands) if (p.staticCommands)
p.Blockchange += new Player.BlockchangeEventHandler(Blockchange1); p.Blockchange += new Player.BlockchangeEventHandler(Blockchange1);
@ -63,5 +68,7 @@ namespace MCGalaxy.Commands
Player.SendMessage(p, "%T/maze"); Player.SendMessage(p, "%T/maze");
Player.SendMessage(p, "%HGenerates a random maze between two points."); Player.SendMessage(p, "%HGenerates a random maze between two points.");
} }
struct CatchPos { public ushort x, y, z; public int randomizer; }
} }
} }

View File

@ -26,8 +26,12 @@ namespace MCGalaxy.Drawing.Ops {
public override string Name { get { return "Maze"; } } public override string Name { get { return "Maze"; } }
public static int randomizer = 0; internal int randomizer = 0;
public static bool[,] wall; bool[,] wall;
RNGCryptoServiceProvider rng1;
Random rng2;
byte[] r = new byte[1];
int width, length;
public override int GetBlocksAffected(Level lvl, Vector3U16[] marks) { public override int GetBlocksAffected(Level lvl, Vector3U16[] marks) {
int lenX = (Math.Abs(marks[1].X - marks[0].X) + 1) / 2; int lenX = (Math.Abs(marks[1].X - marks[0].X) + 1) / 2;
@ -36,14 +40,14 @@ namespace MCGalaxy.Drawing.Ops {
} }
public override void Perform(Vector3U16[] marks, Player p, Level lvl, Brush brush) { public override void Perform(Vector3U16[] marks, Player p, Level lvl, Brush brush) {
int width = Max.X - Min.X; width = Max.X - Min.X;
if (width % 2 != 0) { width++; Min.X--; } if (width % 2 != 0) { width++; Min.X--; }
width -= 2; width -= 2;
int length = Max.Z - Min.Z; length = Max.Z - Min.Z;
if (length % 2 != 0) { length++; Min.Z--; } if (length % 2 != 0) { length++; Min.Z--; }
length -= 2; length -= 2;
if (width < 0 || length < 0) { if (width <= 0 || length <= 0) {
Player.SendMessage(p, "The corners of the maze need to be further apart."); return; Player.SendMessage(p, "The corners of the maze need to be further apart."); return;
} }
Player.SendMessage(p, "Generating maze... this could take a while"); Player.SendMessage(p, "Generating maze... this could take a while");
@ -54,37 +58,32 @@ namespace MCGalaxy.Drawing.Ops {
{ {
wall[w, h] = true; wall[w, h] = true;
} }
rng1 = new RNGCryptoServiceProvider();
rng2 = new Random();
GridNode.maxX = width; Stack<GridNode> stack = new Stack<GridNode>(width * length);
GridNode.maxY = length; stack.Push(new GridNode(0, 0));
//Make a Stack
Stack<GridNode> s = new Stack<GridNode>(width * length);
//Random rand = new Random(DateTime.Now.Millisecond);//ha yeah randomized :P
//lets begin in the lower left corner eh?(0,0)
s.Push(new GridNode(0, 0));
wall[0, 0] = false; wall[0, 0] = false;
while (true) { while (true) {
GridNode node = s.Peek(); GridNode P = stack.Peek();
if (node.turnsPossible()) { if (TurnsPossible(P)) {
GridNode[] nodearray = node.getRandomNext(); GridNode P1, P2;
wall[nodearray[0].X, nodearray[0].Y] = false; MoveRandomDir(P, out P1, out P2);
wall[nodearray[1].X, nodearray[1].Y] = false; wall[P1.X, P1.Y] = false;
s.Push(nodearray[1]); wall[P2.X, P2.Y] = false;
stack.Push(P2);
//we get the next two nodes //we get the next two nodes
//the first is a middle node from which there shouldnt start a new corridor //the first is a middle node from which there shouldnt start a new corridor
//the second is added to the stack. next try will be with this node //the second is added to the stack. next try will be with this node
//i hope this will work this time... //i hope this will work this time...
} else { } else {
s.Pop();//if this node is a dead and it will be removed stack.Pop();//if this node is a dead and it will be removed
} }
if (s.Count < 1) break;//if no nodes are free anymore we will end the generation here if (stack.Count < 1) break;//if no nodes are free anymore we will end the generation here
} }
Player.SendMessage(p, "Maze is generated. now painting..."); Player.SendMessage(p, "Generated maze, now drawing.");
//seems to be there are no more moves possible
ushort minX = Min.X, minZ = Min.Z, maxX = Max.X, maxZ = Max.Z, y = Min.Y; ushort minX = Min.X, minZ = Min.Z, maxX = Max.X, maxZ = Max.Z, y = Min.Y;
maxX++; maxZ++;
for (ushort xx = 0; xx <= width; xx++) for (ushort xx = 0; xx <= width; xx++)
for (ushort zz = 0; zz <= length; zz++) for (ushort zz = 0; zz <= length; zz++)
if (wall[xx, zz]) if (wall[xx, zz])
@ -110,85 +109,58 @@ namespace MCGalaxy.Drawing.Ops {
randomizer = 0; randomizer = 0;
} }
private class GridNode void MoveRandomDir(GridNode P, out GridNode P1, out GridNode P2) {
{ while (true) {
public static int maxX = 0; r[0] = 0;
public static int maxY = 0; if (randomizer == 0) {
public ushort X; rng1.GetBytes(r);
public ushort Y;
private Random rand2 = new Random(Environment.TickCount);
public GridNode[] getRandomNext() {
byte[] r = new byte[1];
switch (randomizer) {
case 0:
RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
rand.GetBytes(r);
r[0] /= (255 / 4); r[0] /= (255 / 4);
break; } else {
default: r[0] = (byte)rng2.Next(4);
r[0] = (byte)rand2.Next(4);
break;
} }
ushort rx = 0, ry = 0, rx2 = 0, ry2 = 0;
switch (r[0]) { switch (r[0]) {
case 0: //go up case 0: //go up
if (isWall(X, Y + 2)) { if (IsWall(P.X, P.Y + 2)) {
rx = X; P1 = new GridNode(P.X, (ushort)(P.Y + 1));
rx2 = X; P2 = new GridNode(P.X, (ushort)(P.Y + 2));
ry = (ushort)(Y + 1); return;
ry2 = (ushort)(Y + 2); } break;
} else {
return this.getRandomNext();
}
break;
case 1: //go down case 1: //go down
if (isWall(X, Y - 2)) { if (IsWall(P.X, P.Y - 2)) {
rx = X; P1 = new GridNode(P.X, (ushort)(P.Y - 1));
rx2 = X; P2 = new GridNode(P.X, (ushort)(P.Y - 2));
ry = (ushort)(Y - 1); return;
ry2 = (ushort)(Y - 2); } break;
} else {
return this.getRandomNext();
}
break;
case 2: //go right case 2: //go right
if (isWall(X + 2, Y)) { if (IsWall(P.X + 2, P.Y)) {
rx = (ushort)(X + 1); P1 = new GridNode((ushort)(P.X + 1), P.Y);
rx2 = (ushort)(X + 2); P2 = new GridNode((ushort)(P.X + 2), P.Y);
ry = Y; return;
ry2 = Y; } break;
} else { case 3: //go left
return this.getRandomNext(); if (IsWall(P.X - 2, P.Y)) {
P1 = new GridNode((ushort)(P.X - 1), P.Y);
P2 = new GridNode((ushort)(P.X - 2), P.Y);
return;
} break;
} }
break;
case 3:
if (isWall(X - 2, Y)) {
//go left
rx = (ushort)(X - 1);
rx2 = (ushort)(X - 2);
ry = Y;
ry2 = Y;
} else {
return this.getRandomNext();
} }
break;
}
return new GridNode[] { new GridNode(rx, ry), new GridNode(rx2, ry2) };
} }
public bool turnsPossible() { bool TurnsPossible(GridNode P) {
return (isWall(X, Y + 2) || isWall(X, Y - 2) || isWall(X + 2, Y) || isWall(X - 2, Y)); return IsWall(P.X, P.Y + 2) || IsWall(P.X, P.Y - 2)
|| IsWall(P.X + 2, P.Y) || IsWall(P.X - 2, P.Y);
} }
private bool isWall(int x, int y) { bool IsWall(int x, int y) {
try { if (x < 0 || y < 0 || x >= width || y >= length) return false;
return wall[x, y]; return wall[x, y];
} catch (IndexOutOfRangeException) {
return false;
}
} }
struct GridNode {
public ushort X, Y;
public GridNode(ushort x, ushort y) { public GridNode(ushort x, ushort y) {
X = x; Y = y; X = x; Y = y;
} }