示例#1
0
		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;
		}
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
 public uint GetRandom(byte id, MTRandom rnd)
 {
     return(this.GetAt(id, rnd.GetUInt32(), rnd.GetUInt32()));
 }
示例#5
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        /// <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);
        }
示例#8
0
		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;
		}
示例#9
0
		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;
		}
示例#10
0
		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;
		}