public int GetDirection(MTRandom rnd) { var visited = true; var direction = 0; while (visited) { direction = (int)rnd.GetUInt32() & 3; visited = this.Directions[direction] != 0; } this.Directions[direction] = 1; return direction; }
public int GetDirection(MTRandom rnd) { var visited = true; var direction = 0; while (visited) { direction = (int)rnd.GetUInt32() & 3; visited = this.Directions[direction] != 0; } this.Directions[direction] = 1; return(direction); }
private int GenerateSubPathRandomDir(MTRandom rnd, int[] directions) { for (int i = 0; i < 4; i++) { if (directions[i] == 0) { while (true) { int random_dir = (int)(rnd.GetUInt32() & 3); if (directions[random_dir] == 0) { directions[random_dir] = 1; return(random_dir); } } } } return(-1); }
public uint GetRandom(byte id, MTRandom rnd) { return(this.GetAt(id, rnd.GetUInt32(), rnd.GetUInt32())); }
public bool GenerateSubPath(MTRandom rnd, int coverageFactor, int branchProbability) { if (!this.isCriticalPathGenerated) { return(false); } if (this.isSubPathGenerated) { return(true); } if (coverageFactor > 100) { coverageFactor = 100; } if (branchProbability > 100) { branchProbability = 100; } var freeRooms = 0; for (int y = 0; y < this.Height; ++y) { for (var x = 0; x < this.Width; ++x) { if (!this.Rooms[x][y].Occupied) { freeRooms += 1; } } } var coverage = (int)(freeRooms * coverageFactor / 100); var toVector = new List <Position>(); if (this.CriticalPath.Count > 0) { foreach (var move in this.CriticalPath) { toVector.Add(move.PosTo); } toVector.RemoveAt(toVector.Count - 1); } toVector = this.GenerateSubPathSub1(toVector); if (coverage <= 0) { return(true); } var tempVector = new List <Position>(); for (int i = 0; i < coverage; ++i) { var vect = toVector; var flag = false; if (tempVector.Count == 0) { if (toVector.Count == 0) { break; } flag = true; } else { if (toVector.Count == 0) { flag = false; vect = tempVector; } else { var rndNum = rnd.GetUInt32() % 100; flag = branchProbability >= rndNum; if (!flag) { vect = tempVector; } } } int rndIndex = (int)(rnd.GetUInt32() % (uint)vect.Count()); var pos = vect[rndIndex]; var room = this.GetRoom(pos); var directions = new int[] { 0, 0, 0, 0 }; var rndDirection = -1; var direction = 0; while (true) { rndDirection = this.GenerateSubPathRandomDir(rnd, directions); if (room.GetPassageType(rndDirection) == 0) { if (this.IsRoomInDirectionFree(pos, rndDirection)) { break; } } direction += 1; if (direction >= 4) { break; } } if (direction >= 4) { tempVector = this.GenerateSubPathSub3(tempVector, toVector); toVector = this.GenerateSubPathSub1(toVector); continue; } var biasedPos = pos.GetBiasedPosition(rndDirection); var room2 = this.GetRoom(biasedPos); room.Directions[rndDirection] = 2; room2.Directions[Direction.GetOppositeDirection(rndDirection)] = 1; _counter += 1; room2.VisitedCount = _counter; tempVector.Add(biasedPos); if (!flag) { tempVector.RemoveAt(rndIndex); toVector.Add(pos); } tempVector = this.GenerateSubPathSub3(tempVector, toVector); toVector = this.GenerateSubPathSub1(toVector); } this.isSubPathGenerated = true; return(true); }
private bool GenerateCriticalPathRecursive(int critPathPos, int critPathMin, int critPathMax, int direction, MTRandom rnd) { var directions = new int[4]; _critPathMaxResult += 1; if (_critPathMaxResult <= 10 * critPathMax) { if (critPathMin <= critPathPos && critPathPos <= critPathMax && this.IsRoomInDirectionFree(_currentPos, StartDirection)) { this.StartPos = _currentPos; foreach (var move in this.CriticalPath) { int temp = move.PosFrom.X; move.PosFrom.X = move.PosTo.X; move.PosTo.X = temp; temp = move.PosFrom.Y; move.PosFrom.Y = move.PosTo.Y; move.PosTo.Y = temp; move.Direction = Direction.GetOppositeDirection(move.Direction); } this.CriticalPath.Reverse(); return(true); } else { critPathPos += 1; var count = 0; if (critPathPos <= critPathMax) { if (direction != -1) { direction = Direction.GetOppositeDirection(direction); } for (int i = 0; i < 4; i++) { if (i == direction) { directions[i] = 0; } else { var next_pos = _currentPos.GetBiasedPosition(i); directions[i] = Sub(next_pos); count += directions[i]; } } while (count > 0) { var rndNum = rnd.GetUInt32() % count + 1; int cnt2 = 0; var iDir = 0; while (iDir < 4) { cnt2 += directions[iDir]; if (cnt2 >= rndNum) { break; } iDir++; } count -= directions[iDir]; directions[iDir] = 0; if (this.MakeMove(iDir)) { if (this.GenerateCriticalPathRecursive(critPathPos, critPathMin, critPathMax, iDir, rnd)) { return(true); } this.UndoMove(); } } } } } return(false); }
/// <summary> /// Finds appropriate place to use as unlock place for given locked place. /// </summary> /// <param name="lockedPlace"></param> /// <returns>Index of unlock place in Places list</returns> public int GetUnlock(PuzzlePlace lockedPlace) { var lockedPlaceIndex = lockedPlace.PlaceIndex; // Get index of room behind lockedPlace door. lockedPlaceIndex = this.Places[lockedPlaceIndex].Room.Neighbor[lockedPlace.DoorDirection].RoomIndex; if (lockedPlaceIndex == 0 || lockedPlaceIndex == -1) // should be last room in section. { lockedPlaceIndex = this.Places.Count; } List <int> possiblePlacesOnPath = new List <int>(); List <int> possiblePlacesNotOnPath = new List <int>(); var deadEnd = -1; var deadEndDepth = 0; RoomTrait room; // places before lockedPlaceIndex are always behind it. for (var i = 0; i < lockedPlaceIndex; ++i) { room = this.Places[i].Room; if (!this.Places[i].IsUsed && !room.isLocked && room.RoomType != RoomType.Start) { // Check is this place have locked doors. // Locked places tend to not reserve themselves, so they could share place with some puzzle, like another locked place. // But they couldn't be shared with unlock places, because they have to control all doors. var haveLockedDoors = false; for (var j = 0; j < 4; ++j) { if (room.DoorType[j] == (int)DungeonBlockType.DoorWithLock && room.Links[j] == LinkType.To) { haveLockedDoors = true; break; } } if (!haveLockedDoors) { var emptyNeighborCount = 0; for (var dir = 0; dir < 4; ++dir) { if (room.IsLinked(dir) && !room.Neighbor[dir].isReserved) { emptyNeighborCount++; } } if (emptyNeighborCount < 2) { if (deadEndDepth < this.Places[i].Depth) { deadEnd = i; } } if (room.isOnPath) { possiblePlacesOnPath.Add(i); } else { possiblePlacesNotOnPath.Add(i); } } } } // Chance to not use deepest corner for unlock place. if (_rng.GetUInt32(100) < 40) { deadEnd = -1; } if (possiblePlacesOnPath.Count == 0 && possiblePlacesNotOnPath.Count == 0) { // Convert locked place room back to alley if there are no more locked doors. room = this.Places[lockedPlace.PlaceIndex].Room; room.SetDoorType(lockedPlace.DoorDirection, (int)DungeonBlockType.Alley); room.SetPuzzleDoor(null, lockedPlace.DoorDirection); var isLockedRoom = room.DoorType.Any(x => (x == (int)DungeonBlockType.DoorWithLock || x == (int)DungeonBlockType.BossDoor)); if (!isLockedRoom) { room.isLocked = false; room.RoomType = RoomType.Alley; } // Return locked place door to list on available doors. var lockedDoorCandidate = new LockedDoorCandidateNode(room, lockedPlace.DoorDirection, room.RoomIndex); _lockedDoorCandidates.AddFirst(lockedDoorCandidate); throw new PuzzleException("Out of unlock places."); } var possiblePlaces = (possiblePlacesNotOnPath.Count > 0 ? possiblePlacesNotOnPath : possiblePlacesOnPath); var placeIndex = deadEnd != -1 ? deadEnd : possiblePlaces[(int)_rng.GetUInt32((uint)possiblePlaces.Count)]; // Walk down from current place to our path and add new possible doors to this._lockedDoorCandidates room = this.Places[placeIndex].Room; while (room.RoomType != RoomType.Start) { if (room.isOnPath) { break; } var dir = room.GetIncomingDirection(); room.isOnPath = true; room = room.Neighbor[dir]; // skip reserved doors //if (room.ReservedDoor[Direction.GetOppositeDirection(dir)]) continue; // skip reserved places if (room.isReserved) { continue; } var lockedDoorCandidate = new LockedDoorCandidateNode(room, Direction.GetOppositeDirection(dir), room.RoomIndex); _lockedDoorCandidates.AddFirst(lockedDoorCandidate); } return(placeIndex); }
public bool GenerateSubPath(MTRandom rnd, int coverageFactor, int branchProbability) { if (!this.isCriticalPathGenerated) return false; if (this.isSubPathGenerated) return true; if (coverageFactor > 100) coverageFactor = 100; if (branchProbability > 100) branchProbability = 100; var freeRooms = 0; for (int y = 0; y < this.Height; ++y) { for (var x = 0; x < this.Width; ++x) { if (!this.Rooms[x][y].Occupied) freeRooms += 1; } } var coverage = (int)(freeRooms * coverageFactor / 100); var toVector = new List<Position>(); if (this.CriticalPath.Count > 0) { foreach (var move in this.CriticalPath) toVector.Add(move.PosTo); toVector.RemoveAt(toVector.Count - 1); } toVector = this.GenerateSubPathSub1(toVector); if (coverage <= 0) return true; var tempVector = new List<Position>(); for (int i = 0; i < coverage; ++i) { var vect = toVector; var flag = false; if (tempVector.Count == 0) { if (toVector.Count == 0) break; flag = true; } else { if (toVector.Count == 0) { flag = false; vect = tempVector; } else { var rndNum = rnd.GetUInt32() % 100; flag = branchProbability >= rndNum; if (!flag) vect = tempVector; } } int rndIndex = (int)(rnd.GetUInt32() % (uint)vect.Count()); var pos = vect[rndIndex]; var room = this.GetRoom(pos); var directions = new int[] { 0, 0, 0, 0 }; var rndDirection = -1; var direction = 0; while (true) { rndDirection = this.GenerateSubPathRandomDir(rnd, directions); if (room.GetPassageType(rndDirection) == 0) { if (this.IsRoomInDirectionFree(pos, rndDirection)) break; } direction += 1; if (direction >= 4) break; } if (direction >= 4) { tempVector = this.GenerateSubPathSub3(tempVector, toVector); toVector = this.GenerateSubPathSub1(toVector); continue; } var biasedPos = pos.GetBiasedPosition(rndDirection); var room2 = this.GetRoom(biasedPos); room.Directions[rndDirection] = 2; room2.Directions[Direction.GetOppositeDirection(rndDirection)] = 1; _counter += 1; room2.VisitedCount = _counter; tempVector.Add(biasedPos); if (!flag) { tempVector.RemoveAt(rndIndex); toVector.Add(pos); } tempVector = this.GenerateSubPathSub3(tempVector, toVector); toVector = this.GenerateSubPathSub1(toVector); } this.isSubPathGenerated = true; return true; }
private bool GenerateCriticalPathRecursive(int critPathPos, int critPathMin, int critPathMax, int direction, MTRandom rnd) { var directions = new int[4]; _critPathMaxResult += 1; if (_critPathMaxResult <= 10 * critPathMax) { if (critPathMin <= critPathPos && critPathPos <= critPathMax && this.IsRoomInDirectionFree(_currentPos, StartDirection)) { this.StartPos = _currentPos; foreach (var move in this.CriticalPath) { int temp = move.PosFrom.X; move.PosFrom.X = move.PosTo.X; move.PosTo.X = temp; temp = move.PosFrom.Y; move.PosFrom.Y = move.PosTo.Y; move.PosTo.Y = temp; move.Direction = Direction.GetOppositeDirection(move.Direction); } this.CriticalPath.Reverse(); return true; } else { critPathPos += 1; var count = 0; if (critPathPos <= critPathMax) { if (direction != -1) direction = Direction.GetOppositeDirection(direction); for (int i = 0; i < 4; i++) { if (i == direction) directions[i] = 0; else { var next_pos = _currentPos.GetBiasedPosition(i); directions[i] = Sub(next_pos); count += directions[i]; } } while (count > 0) { var rndNum = rnd.GetUInt32() % count + 1; int cnt2 = 0; var iDir = 0; while (iDir < 4) { cnt2 += directions[iDir]; if (cnt2 >= rndNum) break; iDir++; } count -= directions[iDir]; directions[iDir] = 0; if (this.MakeMove(iDir)) { if (this.GenerateCriticalPathRecursive(critPathPos, critPathMin, critPathMax, iDir, rnd)) return true; this.UndoMove(); } } } } } return false; }
private int GenerateSubPathRandomDir(MTRandom rnd, int[] directions) { for (int i = 0; i < 4; i++) { if (directions[i] == 0) { while (true) { int random_dir = (int)(rnd.GetUInt32() & 3); if (directions[random_dir] == 0) { directions[random_dir] = 1; return random_dir; } } } } return -1; }