Пример #1
0
    /// <summary>
    /// True = valid placement found, room has been updated to the correct offset.
    /// False = no valid connections, room has been updated to last tried offset (but is probably useless).
    /// </summary>
    /// <param name="room"></param>
    /// <param name="door"></param>
    /// <param name="directions"></param>
    /// <returns></returns>
    private static bool CheckRoomAgainstGrid( Room room, FloorTile door, Directions[] directions )
    {
      // kind of cumbersome, but allows random selection and deletion by reference.
      //   Arrays are more difficult to remove things from.
      List<Directions> dirs = new List<Directions>();
      for( int i=0; i<directions.Length; i++ )
        dirs.Add(directions[i]);

      // try attaching to the north
      int w = room.cells.GetLength(0);
      int h = room.cells.GetLength(1);

      Directions d;

      // Pick a direction specified, and test it.  
      // Avoids obvious bias against North, and allows specific tests for certain room types (halls, for example)
      while( dirs.Count > 0 )
      {
        d = dirs[rand.Next(dirs.Count)];
        dirs.Remove(d);

        switch( d )
        {
          case Directions.North:  // try attaching to the north
            room.SetRoomPosition(door.x - w/2, door.y-h+1);
            if( CheckRoomTilesAgainstGrid(room, door) )
              return true;
            break;

          case Directions.South: // try attaching to the south
            room.SetRoomPosition(door.x - w/2, door.y);
            if( CheckRoomTilesAgainstGrid(room, door) )
              return true;
            break;

          case Directions.East: // try attaching to the east
            room.SetRoomPosition(door.x-w+1, door.y-h/2);
            if( CheckRoomTilesAgainstGrid(room, door) )
              return true;
            break;

          case Directions.West: // try attaching to the west
            room.SetRoomPosition(door.x, door.y-h/2);
            if( CheckRoomTilesAgainstGrid(room, door) )
              return true;
            break;
        }
      }

      // no valid connection found.
      return false;
    }
Пример #2
0
    /// <summary>
    /// Tries to place the specified room.
    /// True = successful, and the connecting door has been flagged.
    /// False = unable to find a connection.
    /// </summary>
    /// <param name="rooms"></param>
    /// <param name="room"></param>
    /// <param name="roomType"></param>
    /// <param name="allowConnectionBias"></param>
    /// <param name="targetDoor"></param>
    /// <returns></returns>
    private static bool PlaceRoom(List<Room> rooms, Room room, CastleRoomType roomType, bool allowConnectionBias, FloorTile targetDoor )
    {
      int w = room.cells.GetLength(0);
      int h = room.cells.GetLength(1);

      if( rooms.Count == 0 )
      {
        // place in middle
        room.SetRoomPosition(grid.GetLength(0)/2 - w/2, grid.GetLength(1)/2 - h/2);
      }
      else
      {
        // pick a door to attach to, build from there.
        List<FloorTile> doors = new List<FloorTile>();
        FloorTile connectionDoor = null;

        if( targetDoor != null )
        {
          doors.Add(targetDoor);
        }
        else if( allowConnectionBias )
        {
          switch( roomType )
          {
            case CastleRoomType.LongHall:
              // custom bias to connect long Halls to Great Rooms if at all possible.
              foreach( Room r in rooms )
                if( r.type == CastleRoomType.GreatroomCircle
                  ||r.type == CastleRoomType.GreatRoomSquare
                  ||r.type == CastleRoomType.GreatRoomRectangle
                  )
                  foreach( FloorTile door in r.doors )
                    if( door.type == FloorType.DoorClosed)
                      doors.Add(door);
              break;

            case CastleRoomType.GreatroomCircle:
            case CastleRoomType.GreatRoomRectangle:
            case CastleRoomType.GreatRoomSquare:
              // Greatrooms should try to attach to the end of hallways.
              // Since the LongHall are generated with the end doors first, we can 
              //   reference those tow doors directly without searching though the room's doors list
              foreach( Room r in rooms )
                if( r.type == CastleRoomType.LongHall )
                {
                  if( r.doors[0].type == FloorType.DoorClosed)
                    doors.Add(r.doors[0]);

                  if( r.doors[1].type == FloorType.DoorClosed)
                    doors.Add(r.doors[1]);
                }
              break;

            default:
              // no custom doors list - the default of "All of them" will be used below
              break;
          }
        }

        // Check for custom doors list - if there are none, default to use all doors in all rooms for tries.
        if( doors.Count == 0 )
        {
          foreach( Room r in rooms )
            foreach( FloorTile door in r.doors )
              if( door.type == FloorType.DoorClosed)
                doors.Add(door);
        }


        // In the event of a LongHall, we'd like to attach it so that it 
        //  traveles away from the room being attached to, rather than attaching along the side of the hall.
        Directions[] directions;
        if( roomType == CastleRoomType.LongHall )
        {
          if( w>h )
          {
            // E/W hall - try to attach on East or West side only
            directions = new Directions[] { Directions.East, Directions.West };
          }
          else
          {
            // N/S hall - attach north or south only.
            directions = new Directions[] { Directions.North, Directions.South };
          }
        }
        else
        {
          // all other rooms may try to attach from any direction
          directions = new Directions[] { Directions.North, Directions.East, Directions.South, Directions.West };
        }


        while( doors.Count>0 && connectionDoor==null )
        {
          // pick a door
          // try to attach to it to the N/E/W/S
          //   update room position accordingly
          //   check room.cells against all other room.cells
          // break loop when successful

          FloorTile door = doors[rand.Next(doors.Count)];
          doors.Remove(door);

          if( CheckRoomAgainstGrid(room, door, directions) )
          {
            connectionDoor = door;
            break;
          }
        }


        // failed to place room
        if( connectionDoor == null )
          return false;

        //set the connection door
        foreach( FloorTile cell in room.cells )
          if( cell.x==connectionDoor.x && cell.y==connectionDoor.y )
          {
            cell.type = FloorType.DoorOpen;
            connectionDoor.type = FloorType.DoorOpen;
            break;
          }
      }
      return true;
    }