/// <summary> /// Returns a singleton MazeCode instance. /// </summary> /// <returns></returns> public static MazeCode Instance(int version) { if (instance[version] == null) { instance[version] = new MazeCode(version); } return(instance[version]); }
/// <summary> /// Constructor. /// Create a maze whose parameters are encoded in the given code (see property Code). /// </summary> /// <param name="code">a string of seven letters (case is ignored)</param> public Maze(string code) { int version = MazeCode.GetCodeVersion(code); this.dimensionsObj = MazeDimensions.Instance(version); this.codeObj = MazeCode.Instance(version); codeObj.Decode(code , out this.seed , out this.xSize, out this.ySize ); this.random = RandomFactory.CreateRandom(seed); }
/// <summary> /// Constructor. /// Create a maze with the given dimensions. /// </summary> /// <param name="xSize"></param> /// <param name="ySize"></param> /// <param name="version"></param> /// <param name="seed"></param> internal Maze(int xSize, int ySize, int version, int seed) { this.dimensionsObj = MazeDimensions.Instance(version); this.codeObj = MazeCode.Instance(version); this.xSize = Math.Max(dimensionsObj.MinSize, Math.Min(dimensionsObj.MaxXSize, xSize)); this.ySize = Math.Max(dimensionsObj.MinSize, Math.Min(dimensionsObj.MaxYSize, ySize)); // Get an initial random seed and use that to create the Random. if (seed < 0) { Random r = RandomFactory.CreateRandom(); this.seed = r.Next(codeObj.SeedLimit); } else { this.seed = seed; } this.random = RandomFactory.CreateRandom(this.seed); }
/// <summary> /// Calculate maximum x and y dimensions, based on the desired Maze.Code length. /// </summary> protected void CalculateDimensions(out int xRange, out int yRange) { MazeCode codeObj = MazeCode.Instance(codeVersion); double codeLimit = Math.Pow(codeObj.CodeDigitRange, codeObj.CodeLength); if (codeLimit > long.MaxValue) { throw new Exception("Maze.Code is too large to be represented as a 64 bit integer"); } codeLimit /= codeObj.SeedLimit; // (MaxXSize - MinSize + 1) // (MaxYSize - MinSize + 1) if (codeVersion == 0) { codeLimit /= (int)WallPosition.WP_NUM; codeLimit /= (MaxBorderDistance + 1); codeLimit /= (MaxBorderDistance + 1); // (MaxXSize + 1) // (MaxXSize + 1) } double x; if (codeVersion == 0) { /* We want to find the greatest integer MaxXSize and MaxYSize with the limitation: * (x-m) * (y-m) * x * x < c * with: * x = MaxXSize + 1 * y = MaxYSize + 1 = MaxXSize / XYRatio + 1 * m = MinSize * c = codeLimit * r = XYRatio * * This is approximately equivalent to: * x*x*x*x < c*r * or * x = (c*r)^^(1/4) * With m>0, that x is even too small. */ x = Math.Truncate(Math.Pow(codeLimit * XYRatio, 0.25)); while ((x - MinSize) * (x / XYRatio - MinSize) * (x) * (x) < codeLimit) { x = x + 1; } } else { /* We want to find the greatest integer MaxXSize and MaxYSize with the limitation: * (x-m) * (y-m) < c * with: * x = MaxXSize + 1 * y = MaxYSize + 1 = MaxXSize / XYRatio + 1 * m = MinSize * c = codeLimit * r = XYRatio * * This is approximately equivalent to: * x*x*x*x < c*r * or * x = (c*r)^^(1/2) * With m>0, that x is even too small. */ x = Math.Truncate(Math.Pow(codeLimit * XYRatio, 0.5)); while ((x - MinSize) * (x / XYRatio - MinSize) < codeLimit) { x = x + 1; } } /* Now, x is 1 greater than acceptable, i.e. * x-1 = MaxXSize + 1 = MinSize + xRange + 1 * MinSize + yRange = MaxYSize = MaxXSize / XYRatio */ xRange = (int)(x - MinSize - 2); yRange = (int)(MaxXSize / XYRatio - MinSize); // Note: MaxXSize is valid after xRange has been assigned }