Attribute VB_Name = "Rut_Loc" Option Explicit Public Const NUM_LOCPROP_PREDEF = 0 ' nº de propiedades 'predefinidas' Private Const DELIM_CMP = """" Private Const SEPAR_CMP = "," ' comprueba si existe una localidad Public Function ExisteLocalidad(ByVal sNombre As String) As Boolean Dim i As Long If Not bHayLoc Then ExisteLocalidad = False Exit Function End If ' comprueba si la localidad ya existe For i = 0 To UBound(Localidades) If Localidades(i).Nombre = sNombre Then ExisteLocalidad = True Exit Function End If Next ExisteLocalidad = False End Function ' crea una nueva localidad con los datos que le pasemos como parámetros ' devuelve True si pudo crearla o False si no Public Function NuevaLocalidad(ByVal sNombre As String, ByVal sDescCorta As String, _ ByVal sDescLarga As String, ByVal bIluminada As Boolean, ByVal bExterior As Boolean) As Boolean Dim n As Long sNombre = QuitaAcentos(Trim(UCase(sNombre))) If Not bHayLoc Then n = 0 Else If ExisteLocalidad(sNombre) Then MsgBox "La localidad " & sNombre & " está repetida.", vbOKOnly + vbExclamation, "ERROR" NuevaLocalidad = False Exit Function End If n = UBound(Localidades) + 1 End If ReDim Preserve Localidades(n) Localidades(n).Nombre = sNombre Localidades(n).DescCorta = sDescCorta Localidades(n).DescLarga = sDescLarga Localidades(n).Iluminada = bIluminada Localidades(n).Exterior = bExterior ReDim Localidades(n).Conexiones(0) If HayPropUsrLoc Then ReDim Localidades(n).PropUsr(UBound(LocProp) - NUM_LOCPROP_PREDEF) Else ReDim Localidades(n).PropUsr(0) End If Localidades(n).X = -1 Localidades(n).Y = -1 bHayLoc = True NuevaLocalidad = True End Function ' borra una localidad Public Sub BorrarLocalidad(ByVal lPos As Long) Dim sLoc As String Dim i As Long, n As Long If Not bHayLoc Then Exit Sub End If n = UBound(Localidades) If lPos > n Then Exit Sub End If sLoc = Localidades(lPos).Nombre ' primero borramos las conexiones BorrarConexLocalidad sLoc For i = lPos To n - 1 Localidades(i) = Localidades(i + 1) Next If n = 0 Then ReDim Localidades(0) bHayLoc = False Else ReDim Preserve Localidades(n - 1) End If End Sub ' borra conexiones con la localidad especificada Public Sub BorrarConexLocalidad(ByVal sLoc As String) Dim i As Long, j As Long, n As Long For i = 0 To UBound(Localidades) n = UBound(Localidades(i).Conexiones) If n = 0 And Localidades(i).Conexiones(0).Localidad = sLoc Then Localidades(i).Conexiones(0).Localidad = "" Localidades(i).Conexiones(0).Verbo = "" Else For j = 0 To n If Localidades(i).Conexiones(j).Localidad = sLoc Then If j < n Then Do While j < n Localidades(i).Conexiones(j) = Localidades(i).Conexiones(j + 1) j = j + 1 Loop End If ReDim Preserve Localidades(i).Conexiones(n - 1) End If Next End If Next End Sub ' busca la localidad especificada y devuelve el índice de la misma ' o -1 si no la encontró Public Function BuscaLocalidad(ByVal sLocalidad As String) As Long Dim i As Long For i = 0 To UBound(Localidades) If Localidades(i).Nombre = sLocalidad Then BuscaLocalidad = i Exit Function End If Next BuscaLocalidad = -1 End Function ' escribe las localidades en un fichero ' el parámetro 'iFich' es un puntero a un fichero abierto ' y 'NumLoc' es una lista con los números de localidades a guardar ' si NumLoc(0)=-1 se guarda toda la tabla de localidades Public Sub EscribirLocalidades(ByVal iFich As Integer, NumLoc() As Long) Dim bGuardar As Boolean Dim i As Long, j As Long, k As Long, n As Long For i = 0 To UBound(Localidades) ' comprobamos si hay que guardar o no la localidad If NumLoc(0) = -1 Then bGuardar = True Else bGuardar = False For k = 0 To UBound(NumLoc) If i = NumLoc(k) Then bGuardar = True Exit For End If Next End If If bGuardar Then Print #iFich, "*" & Localidades(i).Nombre Print #iFich, "{" & CStr(Len(Localidades(i).DescCorta)) & "}" & Localidades(i).DescCorta Print #iFich, "{" & CStr(Len(Localidades(i).DescLarga)) & "}" & Localidades(i).DescLarga Print #iFich, IIf(Localidades(i).Iluminada, PROP_ACTIV, PROP_DESACTIV) Print #iFich, IIf(Localidades(i).Exterior, PROP_ACTIV, PROP_DESACTIV) Print #iFich, "{" & CStr(Len(Localidades(i).Grafico)) & "}" & Localidades(i).Grafico Print #iFich, "{" & CStr(Len(Localidades(i).Sonido)) & "}" & Localidades(i).Sonido '''Print #iFich, "{" & CStr(Len(Localidades(i).Usuario)) & "}" & Localidades(i).Usuario ' conexiones n = UBound(Localidades(i).Conexiones) Print #iFich, "%" & n For j = 0 To n Print #iFich, Localidades(i).Conexiones(j).Localidad & "#" & _ Localidades(i).Conexiones(j).Verbo & "#" & _ IIf(Localidades(i).Conexiones(j).Abierta, "S", "N") Next ' si hay propiedades definidas por el usuario las guardamos If HayPropUsrLoc Then For j = 0 To UBound(Localidades(i).PropUsr) Print #iFich, "{" & CStr(Len(Localidades(i).PropUsr(j))) & "}" & Localidades(i).PropUsr(j) Next For j = j To UBound(LocProp) - NUM_LOCPROP_PREDEF Print #iFich, "{0}" Next End If Print #iFich, CStr(Localidades(i).X) & "," & CStr(Localidades(i).Y) End If Next End Sub ' guarda la tabla de localidades, devuelve False si error Public Function GuardarLocalidades(ByVal sFich As String) As Boolean Dim iFich As Integer Dim i As Long, NumLoc(0) As Long On Error GoTo Error_GuardarLoc2 iFich = FreeFile Open sFich For Output As #iFich ' propiedades de usuario If HayPropUsrLoc Then For i = NUM_LOCPROP_PREDEF To UBound(LocProp) Print #iFich, DELIM_CMP & CStr(LocProp(i).Tipo) & DELIM_CMP & SEPAR_CMP & _ DELIM_CMP & LocProp(i).Nombre & DELIM_CMP & SEPAR_CMP Next End If ' si está vacia la tabla de localidades sale, pero deja el fichero en blanco If Not bHayLoc Then Close #iFich GuardarLocalidades = True Exit Function End If On Error GoTo Error_GuardarLoc1 NumLoc(0) = -1 EscribirLocalidades iFich, NumLoc Close #iFich GuardarLocalidades = True Exit Function Error_GuardarLoc1: Close #iFich Error_GuardarLoc2: MsgBox "Error al guardar la tabla de localidades: " & Err.Description, _ vbOKOnly + vbCritical, "Error" GuardarLocalidades = False End Function ' lee las localidades de un fichero ' devuelve True si hay localidades Public Function LeerLocalidades(ByVal iFich As Integer, l() As Localidad) As Boolean Dim Conex() As Conexion Dim i As Long, j As Long, n As Long Dim c As String n = 0 Do While Not EOF(iFich) ReDim Preserve l(n) Line Input #iFich, c l(n).Nombre = Mid(c, 2) l(n).DescCorta = LeeDescripcion(iFich) l(n).DescLarga = LeeDescripcion(iFich) Line Input #iFich, c l(n).Iluminada = IIf(c = PROP_ACTIV, True, False) Line Input #iFich, c l(n).Exterior = IIf(c = PROP_ACTIV, True, False) l(n).Grafico = LeeDescripcion(iFich) l(n).Sonido = LeeDescripcion(iFich) '''L(n).Usuario = LeeDescripcion(iFich) If Not LeeConexiones(iFich, Conex) Then Err.Raise 666, , "Error al leer las conexiones" End If j = UBound(Conex) ReDim l(n).Conexiones(j) For i = 0 To j l(n).Conexiones(i).Localidad = Conex(i).Localidad l(n).Conexiones(i).Verbo = Conex(i).Verbo l(n).Conexiones(i).Abierta = Conex(i).Abierta Next ' si hay propiedades definidas por el usuario las cargamos If HayPropUsrLoc Then ReDim Localidades(n).PropUsr(UBound(LocProp) - NUM_LOCPROP_PREDEF) For i = 0 To UBound(Localidades(n).PropUsr) Localidades(n).PropUsr(i) = LeeDescripcion(iFich) Next Else ReDim Localidades(n).PropUsr(0) End If Line Input #iFich, c i = InStr(c, ",") If i > 0 Then l(n).X = CLng(Left(c, i - 1)) l(n).Y = CLng(Mid(c, i + 1)) End If n = n + 1 Loop If n > 0 Then LeerLocalidades = True Else LeerLocalidades = False End If End Function ' carga la tabla de localidades, devuelve False si error Public Function CargarLocalidades(ByVal sFich As String) As Boolean Dim Conex() As Conexion Dim iFich As Integer Dim i As Long, j As Long, n As Long Dim c As String, sTipo As String, sNombre As String On Error GoTo Error_CargarLoc2 PropiedadesLocalidades ReDim Localidades(0) bHayLoc = False iFich = FreeFile Open sFich For Input As #iFich On Error GoTo Error_CargarLoc1 ' si el fichero está vacío, sale If EOF(iFich) Then Close iFich CargarLocalidades = True Exit Function End If ' propiedades de usuario Line Input #iFich, c If Left(c, 1) <> "*" Then ' si no hay propiedades predefinidas cogemos ' como índice -1 para que luego al incrementarse ' empiece en 0, en otro caso cogemos el índice ' del último elemento de la lista If LocProp(0).Nombre = "" Then n = -1 Else n = UBound(LocProp) End If Do While True n = n + 1 ReDim Preserve LocProp(n) sTipo = SeparaCampo(c, 1, DELIM_CMP, SEPAR_CMP) sNombre = SeparaCampo(c, 2, DELIM_CMP, SEPAR_CMP) LocProp(n).Tipo = CInt(sTipo) LocProp(n).Nombre = UCase(sNombre) If EOF(iFich) Then Exit Do Else Line Input #iFich, c If Left(c, 1) = "*" Then Exit Do End If End If Loop End If '''bHayLoc = LeerLocalidades(iFich, Localidades) n = 0 Do While Not EOF(iFich) ReDim Preserve Localidades(n) Localidades(n).Nombre = Mid(c, 2) Localidades(n).DescCorta = LeeDescripcion(iFich) Localidades(n).DescLarga = LeeDescripcion(iFich) Line Input #iFich, c Localidades(n).Iluminada = IIf(c = PROP_ACTIV, True, False) Line Input #iFich, c Localidades(n).Exterior = IIf(c = PROP_ACTIV, True, False) Localidades(n).Grafico = LeeDescripcion(iFich) Localidades(n).Sonido = LeeDescripcion(iFich) '''Localidades(n).Usuario = LeeDescripcion(iFich) If Not LeeConexiones(iFich, Conex) Then Err.Raise 666, , "Error al leer las conexiones" End If j = UBound(Conex) ReDim Localidades(n).Conexiones(j) For i = 0 To j Localidades(n).Conexiones(i).Localidad = Conex(i).Localidad Localidades(n).Conexiones(i).Verbo = Conex(i).Verbo Localidades(n).Conexiones(i).Abierta = Conex(i).Abierta Next ' si hay propiedades definidas por el usuario las cargamos If HayPropUsrLoc Then ReDim Localidades(n).PropUsr(UBound(LocProp) - NUM_LOCPROP_PREDEF) For i = 0 To UBound(Localidades(n).PropUsr) Localidades(n).PropUsr(i) = LeeDescripcion(iFich) Next Else ReDim Localidades(n).PropUsr(0) End If Line Input #iFich, c i = InStr(c, ",") If i > 0 Then Localidades(n).X = CLng(Left(c, i - 1)) Localidades(n).Y = CLng(Mid(c, i + 1)) End If n = n + 1 If Not EOF(iFich) Then Line Input #iFich, c End If Loop Close #iFich If n > 0 Then bHayLoc = True End If CargarLocalidades = True Exit Function Error_CargarLoc1: Close #iFich Error_CargarLoc2: ReDim Localidades(0) bHayLoc = False MsgBox "Error al cargar la tabla de localidades: " & Err.Description, _ vbOKOnly + vbCritical, "Error" CargarLocalidades = False End Function ' lee las conexiones de una localidad del fichero de localidades ' devuelve False si error Private Function LeeConexiones(ByVal iFich As Integer, Conex() As Conexion) As Boolean Dim c As String, sLoc As String, sVerbo As String, sAbierta As String Dim i As Long, j As Long, k As Long, n As Long On Error GoTo Error_LeeConex Line Input #iFich, c n = CLng(Mid(c, 2)) ReDim Conex(n) For i = 0 To n Line Input #iFich, c ' separa los campos de la conexión ' puede tener 2 campos: LOCALIDAD#VERBO ' o 3 campos: LOCALIDAD#VERBO#ABIERTA j = InStr(c, "#") If j > 0 Then sLoc = Left(c, j - 1) k = InStr(j + 1, c, "#") If k = 0 Then sVerbo = Mid(c, j + 1) sAbierta = "S" Else sVerbo = Mid(c, j + 1, k - j - 1) sAbierta = Mid(c, k + 1) End If Conex(i).Localidad = sLoc Conex(i).Verbo = sVerbo Conex(i).Abierta = IIf(sAbierta = "S", True, False) End If Next LeeConexiones = True Exit Function Error_LeeConex: LeeConexiones = False Exit Function End Function ' rellena la tabla de propiedades de las localidades Public Sub PropiedadesLocalidades() If NUM_LOCPROP_PREDEF > 0 Then ReDim LocProp(NUM_LOCPROP_PREDEF - 1) Else ReDim LocProp(0) End If End Sub ' devuelve el valor de una propiedad de una localidad ' también ejecuta los métodos asociados a localidades ' devuelve Chr(0) si error Public Function PropiedadLoc(ByVal sNombre As String, ByVal sPropiedad As String, _ ByVal sParam As String) As String Dim i As Long, lLoc As Long Dim sP1 As String ' si el nombre pasado es un número accedemos a la localidad por su número de orden ' si no por su nombre On Error Resume Next i = CLng(sNombre) If Err.Number = 0 Then lLoc = i If Err.Number <> 0 Then PropiedadLoc = Chr(0) Exit Function End If Else lLoc = BuscaLocalidad(sNombre) If Localidades(lLoc).Nombre = "" Then PropiedadLoc = Chr(0) Exit Function End If End If Err.Clear sPropiedad = UCase(sPropiedad) Select Case UCase(sPropiedad) Case LOC_PROP_NOMBRE PropiedadLoc = Localidades(lLoc).Nombre Case LOC_PROP_DESCCORTA PropiedadLoc = Localidades(lLoc).DescCorta Case LOC_PROP_DESCLARGA PropiedadLoc = Localidades(lLoc).DescLarga Case LOC_PROP_EXTERIOR PropiedadLoc = IIf(Localidades(lLoc).Exterior, EXPR_TRUE, EXPR_FALSE) Case LOC_PROP_ILUMINADA PropiedadLoc = IIf(Localidades(lLoc).Iluminada, EXPR_TRUE, EXPR_FALSE) Case LOC_PROP_GRAFICO PropiedadLoc = Localidades(lLoc).Grafico Case LOC_PROP_SONIDO PropiedadLoc = Localidades(lLoc).Sonido Case LOC_PROP_USUARIO PropiedadLoc = Localidades(lLoc).Usuario Case METODO_CONEX ' LOC[expr].Conexiones() ' devuelve un array con las conexiones de la localidad, los elementos ' impares contienen el verbo y los pares la localidad con la que conecta PropiedadLoc = ConexionesLoc(lLoc) Case METODO_OBJETOS ' LOC[expr].Objetos() ' devuelve un array con los objetos de la localidad PropiedadLoc = ObjetosContenedor(OBJ_CONTLOC, Localidades(lLoc).Nombre) Case METODO_PSIS ' LOC[expr].PSIs() ' devuelve un array con los PSIs de la localidad (sin incluir al del jugador) PropiedadLoc = PSIsLocalidad(Localidades(lLoc).Nombre) Case METODO_METER ' LOC[expr].Meter(objeto) ' pone un objeto en la localidad sP1 = CogeParametro(sParam, 1) sP1 = AnalizaExpresion(sP1) If sP1 = Chr(0) Then PropiedadLoc = Chr(0) Else PropiedadLoc = IIf(PonerObjeto(sP1, OBJ_CONTLOC, CStr(lLoc)), EXPR_TRUE, EXPR_FALSE) End If Case METODO_CONTIENE ' LOC[expr].Contiene(objeto) ' comprueba si en la localidad está un objeto dado sP1 = CogeParametro(sParam, 1) sP1 = AnalizaExpresion(sP1) If sP1 = Chr(0) Then PropiedadLoc = Chr(0) Else PropiedadLoc = IIf(ContieneObjeto(sP1, OBJ_CONTLOC, lLoc), EXPR_TRUE, EXPR_FALSE) End If Case METODO_LOCALIDAD ' LOC[expr].Localidad(verbo) ' devuelve la localidad con la que conecta esta según el verbo de conexión sP1 = CogeParametro(sParam, 1) sP1 = AnalizaExpresion(sP1) PropiedadLoc = ConexLoc(lLoc, sP1) If PropiedadLoc = "" Then PropiedadLoc = EXPR_FALSE End If Case METODO_ABIERTA ' LOC[expr].Abierta(verbo) ' comprueba si una conexión está abierta sP1 = CogeParametro(sParam, 1) sP1 = AnalizaExpresion(sP1) PropiedadLoc = IIf(ConexAbierta(lLoc, sP1), EXPR_TRUE, EXPR_FALSE) Case METODO_ABRIR ' LOC[expr].Abrir(verbo) ' abre una conexión sP1 = CogeParametro(sParam, 1) sP1 = AnalizaExpresion(sP1) CambiaConex lLoc, sP1, True Case METODO_CERRAR ' LOC[expr].Cerrar(verbo) ' cierra una conexión sP1 = CogeParametro(sParam, 1) sP1 = AnalizaExpresion(sP1) CambiaConex lLoc, sP1, False Case Else ' propiedades definidas por el usuario For i = 0 To UBound(LocProp) If UCase(LocProp(i).Nombre) = sPropiedad Then If i < NUM_LOCPROP_PREDEF Then PropiedadLoc = Chr(0) Else PropiedadLoc = Localidades(lLoc).PropUsr(i - NUM_LOCPROP_PREDEF) End If Exit Function End If Next PropiedadLoc = Chr(0) End Select End Function ' asigna un valor a una propiedad de una localidad, devuelve Chr(0) si error Public Function AsignaPropiedadLoc(ByVal sNombre As String, ByVal sPropiedad As String, _ ByVal sValor As String) As String Dim i As Long, lLoc As Long ' si el nombre pasado es un número accedemos a la localidad por su número de orden ' si no por su nombre On Error Resume Next i = CLng(sNombre) If Err.Number = 0 Then lLoc = i If Err.Number <> 0 Then AsignaPropiedadLoc = Chr(0) Exit Function End If Else lLoc = BuscaLocalidad(sNombre) If Localidades(lLoc).Nombre = "" Then AsignaPropiedadLoc = Chr(0) Exit Function End If End If Err.Clear sPropiedad = UCase(sPropiedad) Select Case UCase(sPropiedad) Case LOC_PROP_NOMBRE AsignaPropiedadLoc = Chr(0) Exit Function Case LOC_PROP_DESCCORTA Localidades(lLoc).DescCorta = sValor Case LOC_PROP_DESCLARGA Localidades(lLoc).DescLarga = sValor Case LOC_PROP_EXTERIOR Localidades(lLoc).Exterior = IIf(sValor = EXPR_TRUE, EXPR_TRUE, EXPR_FALSE) Case LOC_PROP_ILUMINADA Localidades(lLoc).Iluminada = IIf(sValor = EXPR_TRUE, EXPR_TRUE, EXPR_FALSE) Case LOC_PROP_GRAFICO Localidades(lLoc).Grafico = sValor Case LOC_PROP_SONIDO Localidades(lLoc).Sonido = sValor Case LOC_PROP_USUARIO Localidades(lLoc).Usuario = sValor Case Else ' propiedades definidas por el usuario For i = 0 To UBound(LocProp) If UCase(LocProp(i).Nombre) = sPropiedad Then If i < NUM_LOCPROP_PREDEF Then AsignaPropiedadLoc = Chr(0) Else Localidades(lLoc).PropUsr(i - NUM_LOCPROP_PREDEF) = sValor End If AsignaPropiedadLoc = sValor Exit Function End If Next AsignaPropiedadLoc = Chr(0) Exit Function End Select AsignaPropiedadLoc = sValor End Function ' devuelve las conexiones de una localidad (en un array en el que los elementos ' impares son el verbo y los pares la localidad con la que conecta) ' devuelve cadena vacía si no tiene Private Function ConexionesLoc(ByVal lLoc As Long) As String Dim i As Long Dim s As String If Localidades(lLoc).Conexiones(0).Verbo = "" Then ConexionesLoc = "" Exit Function End If s = "" For i = 0 To UBound(Localidades(lLoc).Conexiones) s = s & Localidades(lLoc).Conexiones(i).Verbo & Chr(SEPAR_ARRAY) & _ Localidades(lLoc).Conexiones(i).Localidad & Chr(SEPAR_ARRAY) Next ConexionesLoc = s End Function ' devuelve el nombre de la localidad con la que se conecta una a través de un ' verbo de conexión Private Function ConexLoc(ByVal lLoc As Long, ByVal sVerbo As String) As String Dim i As Long sVerbo = UCase(sVerbo) For i = 0 To UBound(Localidades(lLoc).Conexiones) If Localidades(lLoc).Conexiones(i).Verbo = sVerbo Then ConexLoc = Localidades(lLoc).Conexiones(i).Localidad Exit Function End If Next ConexLoc = "" End Function ' devuelve True si la conexión está abierta o False si no Private Function ConexAbierta(ByVal lLoc As Long, ByVal sVerbo As String) As Boolean Dim i As Long sVerbo = UCase(sVerbo) For i = 0 To UBound(Localidades(lLoc).Conexiones) If Localidades(lLoc).Conexiones(i).Verbo = sVerbo Then ConexAbierta = Localidades(lLoc).Conexiones(i).Abierta Exit Function End If Next ' si no hemos encontrado la conexión devolvemos como si estuviese abierta ConexAbierta = True End Function ' cambia una conexión a abierta o cerrado Private Sub CambiaConex(ByVal lLoc As Long, ByVal sVerbo As String, ByVal bAbierta As Boolean) Dim i As Long sVerbo = UCase(sVerbo) For i = 0 To UBound(Localidades(lLoc).Conexiones) If Localidades(lLoc).Conexiones(i).Verbo = sVerbo Then Localidades(lLoc).Conexiones(i).Abierta = bAbierta Exit Sub End If Next End Sub ' devuelve los PSIs que hay en una localidad (en un array), no se incluye al ' que controla el jugador ' devuelve cadena vacía si no encontró ninguno Public Function PSIsLocalidad(ByVal sLoc As String) As String Dim i As Long, lPSIJugador As Long Dim s As String If Not bHayPSI Or Not bHayLoc Then PSIsLocalidad = "" Exit Function End If lPSIJugador = NumPSIJugador s = "" sLoc = UCase(sLoc) For i = 0 To UBound(PSIs) If i <> lPSIJugador And PSIs(i).Localidad = sLoc Then s = s & JuntaNombreAdj(PSIs(i).Nombre, PSIs(i).Adjetivo) & _ Chr(SEPAR_ARRAY) End If Next PSIsLocalidad = s End Function ' devuelve True si hay propiedades de usuario definidas para las localidades Public Function HayPropUsrLoc() As Boolean If UBound(LocProp) >= NUM_LOCPROP_PREDEF And Trim(LocProp(0).Nombre) <> "" Then HayPropUsrLoc = True Else HayPropUsrLoc = False End If End Function