SERIE CONVERSIONES DEL BASIC BBC AL BASIC SINCLAIR Programa : SYLLOGISM Versión base / Basic / Publicado en la página 55 de la revista britanica COMPUTER Answers especial de verano de julio/agosto de 1984. El listado original: 10 REM ***** SYLLOGISM ANALYSER ***** 20 REM ***** by Marcus Jeffery ***** 30 : 40 : 50 MODE 7 60 *FX14,6 70 : 80 PROCIntro 90 PROCInitialize 100 PROCLoad_data 120 REPEAT 130 PROCInput 140 UNTIL Quit% 150 PROCSave_data 160 END 170 : 180 : 190 : 200 REM********************************** 210 DEF PROCIntro 220 CLS 230 FOR I%=10TO11:PRINT TAB(7,I%);CHR$129CHR$141;"SYLLOGISM ANALYZER":NEXT 240 PRINT 'TAB(8);CHR$134;"by Marcus Jeffery" 250 PRINT '''CHR$136CHR$131;" Press";CHR$135;"";CHR$131;"to cont inue" 260 REPEAT UNTIL GET$=" " 270 CLS 280 PRINT ''" You may converse with this program" 290 PRINT " using normal (though limited)" 300 PRINT TAB(10);"English sentences." 310 PRINT '" Type facts in the form:" 320 PRINT CHR$134;" ";CHR$131;" IS ";CHR$134;""; CHR$131;"." 330 PRINT " where the full-stop is optional." 340 PRINT '" Ask questions in the form:" 350 PRINT CHR$131;" IS ";CHR$134;" ";CHR$131;"?" 360 PRINT " where the '?' is compulsory, and" 370 PRINT " the second noun phrase must start" 380 PRINT " with 'A', 'AN' or 'THE'." 390 PRINT '" Sentences are typed after the" 400 PRINT " '?' prompt. Use upper-case to" 410 PRINT " avoid confusion." 420 PRINT " Type";CHR$131;"QUIT";CHR$135;"to terminate input." 430 PRINT 'CHR$136CHR$130;" Press";CHR$135;"";CHR$130;"to continue" 440 REPEAT UNTIL GET$=" " 450 ENDPROC 460 REM********************************** 470 DEF PROCInitialize 480 : 490 CLS 500 Quit%=FALSE 510 maximum%=100 520 workspace%= maximum%*maximum% DIV 8+1 530 : 540 DIM dictionary$(maximum%) 550 FOR i%=0 TO maximum% 560 dictionary$(i%)="" 570 NEXT 580 dictionary%=-1 590 : 600 DIM table% workspace%,covered% workspace% 610 PROCClear(table%) 620 : 630 DIM redundant$(7) 640 FOR i%=0 TO 7: READ redundant$(i%): NEXT 670 DATA "IS ","A ","AN ","THE " 680 DATA " IS "," A "," AN "," THE " 690 : 700 DIM exponent%(7) 710 FOR i%=0 TO 7 720 READ exponent%(i%) 730 NEXT 740 DATA 1,2,4,8,16,32,64,128 750 : 760 ENDPROC 770 REM********************************** 780 DEF PROCInput 790 : 800 INPUT sentence$ 810 : 820 IF sentence$="QUIT" THEN Quit%=TRUE ELSE IF RIGHT$(sentence$,1)="?" THEN PROCQuestion ELSE PROCFact 830 : 840 ENDPROC 850 REM********************************** 860 DEF PROCFact 870 : 880 IF RIGHT$(sentence$,1)="." THEN sentence$=LEFT$(sentence$,LEN(sentence$) -1) 890 : 900 PROCSplit (4,4) 910 IF j%>LEN(sentence$) THEN PRINT CHR$129;"I don't understand this."' "Please could you rephrase it?": ENDPROC 920 PRINT CHR$131;"I understand." 930 : 940 Lower%= FNinsert_into_dictionary(lower$) 950 Upper%= FNinsert_into_dictionary(upper$) 960 : 970 PROCinsert_into_table(table%,Lower%,Lower%) 980 PROCinsert_into_table(table%,Upper%,Upper%) 990 PROCinsert_into_table(table%,Lower%,Upper%) 1000 : 1010 ENDPROC 1020 REM********************************** 1030 DEF PROCQuestion 1040 : 1050 sentence$=LEFT$(sentence$,LEN(sentence$)-1) 1060 : 1070 PROCSplit(5,7) 1080 IF j%>LEN(sentence$) THEN PRINT CHR$129;"I don't understand the question. ":ENDPROC 1090 : 1100 No_info%=FALSE 1110 Present%=dictionary% 1120 Lower%= FNinsert_into_dictionary(lower$) 1130 IF Lower%=maximum% OR Lower%>Present% THEN PRINT CHR$134;"I have no information on:"'TAB(5);CHR$130;lower$: dictionary%=Present%: No_info%=TRUE 1140 Upper%= FNinsert_into_dictionary(upper$) 1150 IF Upper%=maximum% OR Upper%>Present% THEN PRINT CHR$134;"I have no information on:"'TAB(5);CHR$130;upper$: dictionary%=Present%: No_info%=TRUE 1160 IF No_info% THEN ENDPROC 1170 : 1180 PROCClear(covered%) 1190 IF FNSearch(Upper%) THEN PRINT CHR$131;"YES." ELSE PRINT CHR$131;"I DON'T KNOW." 1200 : 1210 ENDPROC 1220 REM********************************** 1230 DEF PROCSplit(Lower%,Upper%) 1240 : 1250 FOR i%=1 TO LEN(sentence$) 1260 IF MID$(sentence$,i%,2)=" " THEN sentence$=LEFT$(sentence$,i%)+MID$( s$,i+2): GOTO 1260 1270 NEXT 1280 sentence$= FNRemove(sentence$) 1290 : 1300 j%=1 1310 REPEAT 1320 split%=FALSE 1330 FOR i%=Lower% TO Upper% 1340 IF MID$(sentence$,j%,LEN(redundant$(i%)))=redundant$(i%) THEN lower$= LEFT$(sentence$,j%-1): upper$=MID$(sentence$,j%+LEN(redundant$(i%))): split%= TRUE 1350 NEXT 1360 j%=j%+1 1370 UNTIL split% OR j%>LEN(sentence$) 1380 : 1390 lower$= FNRemove(lower$) 1400 upper$= FNRemove(upper$) 1410 : 1420 ENDPROC 1430 REM********************************** 1440 DEF FNRemove(noun$) 1450 : 1460 REPEAT 1470 Removed%=FALSE 1480 FOR i%=0 TO 7 1490 IF LEFT$(noun$, LEN(redundant$(i%)))=redundant$(i%) THEN noun$=MID$( noun$,LEN(redundant$(i%))):Removed%=TRUE 1500 IF LEFT$(noun$,1)=" " THEN noun$=MID$(noun$,2):Removed%=TRUE 1510 IF RIGHT$(noun$,1)=" " THEN noun$=LEFT$(noun$,LEN(noun$)-1):Removed% =TRUE 1520 NEXT 1530 UNTIL NOT Removed% 1540 : 1550 =noun$ 1560 REM********************************** 1570 DEF FNinsert_into_dictionary(noun$) 1580 : 1590 dictionary$(dictionary%+1)=noun$ 1600 : 1610 i%=-1 1620 : 1630 REPEAT 1640 i%=i%+1 1650 UNTIL dictionary$(i%)=noun$ 1660 : 1670 IF i%=maximum% THEN PRINT CHR$129;"No dictionary room for:";noun$ ELSE IF i%>dictionary% THEN dictionary%=i% 1680 : 1690 =i% 1700 REM********************************** 1710 DEF PROCinsert_into_table(base%,x%,y%) 1720 : 1730 z%= maximum%*x%+y% 1740 x%= z% DIV 8 1750 y%= z% MOD 8 1760 base%?x% = base%?x% OR exponent%(y%) 1770 : 1780 ENDPROC 1790 REM********************************** 1800 DEF FNGet_value(base%,x%,y%) 1810 : 1820 z%= maximum%*x%+y% 1830 x%= z% DIV 8 1840 y%= z% MOD 8 1850 =-(base%?x% AND exponent%(y%)) DIV exponent%(y%) 1860 DEF PROCClear(base%) 1870 : 1880 FOR i%=0 TO workspace% 1890 base%?i%=0 1900 NEXT 1910 : 1920 ENDPROC 1930 REM********************************** 1940 DEF FNSearch(from%) 1950 LOCAL i% 1970 IF from%=Lower% THEN =TRUE 1980 : 1990 i%=0 2000 IF FNGet_value(table%,i%,fr%) AND NOT FNGet_value(covered%,i%,fr%) THEN PROCinsert_into_table (covered%,i%,fr%): IF FNSearch(i%) THEN =TRUE 2010 IF i%"Y" THEN GOTO 2070 2090 : 2100 PRINT '"Position tape at start of SIR_DICT" 2110 PRINT "then press any key to load...." 2120 Wait$= GET$ 2130 : 2140 File= OPENIN"SIR_DICT" 2150 : 2160 INPUT #File%,Number% 2170 IF Number% <= maximum% THEN GOTO 2260 2180 PRINT 'CHR$129;"The dictionary size of the saved" 2190 PRINT CHR$129;"data (";Number%;") is inconsistent" 2200 PRINT CHR$129;"with the present size." 2210 PRINT CHR$129;"Set the value of 'maximum%' in" 2220 PRINT CHR$129;"PROCinitialise to this value," 2230 PRINT CHR$129;"or greater, and rerun the program" 2240 END 2250 : 2260 PRINT 'CHR$130;"Loading dictionary..." 2270 REPEAT 2280 dictionary%= dictionary%+1 2290 INPUT#File%, dictionary$(dictionary%) 2300 UNTIL EOF#File% 2310 CLOSE#File% 2320 : 2330 File%= OPENIN"SIR_TBLE" 2340 PRINT 'CHR$130;"Loading table..." 2350 i%= 0 2360 : 2370 REPEAT 2380 byte%= BGET#(File%) 2390 FOR j%=0 TO 7 2400 IF byte% AND exponent%(j%)THEN x%=(8*i%+j%)DIV number%: y%=(8*i% +j%)MOD number%: PROCinsert_into_table(table%,x%,y%) 2410 NEXT 2420 i%= i%+1 2430 UNTIL EOF#File% 2440 CLOSE#File% 2450 : 2460 PRINT 'CHR$130;" INPUT COMPLETE" 2470 FOR J%=1 TO 10000:NEXT:CLS 2480 : 2490 ENDPROC 2500 REM********************************** 2510 DEF PROCSave_data 2520 : 2530 CLS 2540 INPUT "Do you want to save the data? (Y/N) ";Answer$ 2550 IF Answer$="N" THEN ENDPROC ELSE IF Answer$<>"Y" THEN GOTO 2540 2560 : 2580 Wait$= GET$ 2590 : 2600 PRINT 'CHR$130;"Saving dictionary..." 2610 File%= OPENOUT"SIR_DICT" 2620 PRINT#File%, maximum% 2630 FOR i%=0 TO dictionary% 2640 PRINT#File%, dictionary% 2650 NEXT 2660 CLOSE#File% 2670 : 2680 PRINT 'CHR$130;"Saving table..." 2690 File%= OPENOUT"SIR_TBLE" 2700 FOR i%=0 TO workspace% 2710 BPUT#File%, table%?i% 2720 NEXT 2730 CLOSE#File% 2740 : 2750 PRINT 'CHR$130;" FINISHED SAVING DATA" 2760 : 2770 ENDPROC 2780 REM********************************** 2790 REM********************************** PORTANDOLO AL SPECTRUM La estructura del listado Basic es la sigte.: 10-160: el bloque principal 210-450: procedimiento introductorio 470-760: " inicializar 780-840: " input 860-1010: " fact 1030-1210: " cuestion 1230-1420: " separar 1440-1550: funcion remover 1570-1690: " insertar en el diccionario 1710-1780: " " en la tabla 1800-1850: " conseguir valor 1860-1920: proc. limpiar 1940-2030: funcion de busqueda 2050-2490: proc. cargar datos 2510-2770: " salvar datos Lista de variables EN EL BBC EN EL SPECTRUM USO base% b insertar en tabla y conseguir valor byte% carga la tabla del mapa de bits covered% cov direccion base del " de " dictionary% d puntero de palabras en la matriz diccionario$ exponent% e() matriz numerica de 8 elementos file% ficheros de lectura y escritura a cinta from% fr indica columna a usar en proc. buscar i%, j% i,j variables de conteo FOR lower% lo ubica primer sustantivo en una frase maximum% max el maximo de palabras a guardar en el dicc. no_info% noinfo var. logica del proc. cuestion number% contiene el valor maximo tras cargar los datos present% prs contiene temporalmente el puntero dicc. quit% quit var. logica para salir del prog. removed% rmvd controla bucle REPEAT en funcion remover split% split var. logica del proc. separar table% tbl dir. base del mapa de bits de la tabla deductiva upper% up pos. segundo sustantivo en la frase x%,y%,z% x,y,z insertar en tabla y conseguir valor answer$ a$ procedimientos para salvar y cargar los datos dictionary$ d$() matriz conteniendo los sustantivos de las frases lower$ l$ contiene el primer sust. noun$ n$ funciones remover e insertar en dicc. redundant$ r$() matriz para las cadenas redundantes sentence$ s$ almacena cada sentencia tipeada upper$ u$ segundo sust. de la frase wait$ w$ espera se pulse una tecla en salvar y cargar Las variables de cadena largas en el BBC, son forzosamente cambiadas a una sola letra junto con las matrices por convencion del Basic Sinclair, mientras las variables numericas si bien el Spectrum acepta nombres largos, los acorte por razones de brevedad de tipeo y ahorrar espacio. En cuanto a la linea: 600 DIM table% workspace%,covered% workspace% lo que esto hace es definir no una matriz sino una tabla de mapa de bits. Para su conversion al Spectrum tenia tres opciones: 1. usar DIM t(wks):DIM c(wks) -lo cual ocupa mas espacio en RAM 2. DIM t$(wks):DIM c$(wks) - lo que hace que cada valor ocupe un bite solo 3. LET tbl=pos m en ram:LET cov=pos n en ram En mi caso opte por la tercera, asi que elegi 44000 para tbl y 45255 por cov. Debido a que el BBC usa procedimientos y estructuracion, elegi convertirlo al Betabasic 3 para poderlo tipear y se viese lo mas cercano al listado original. Los nombres demasiado largos a mi parecer decidi reducirlos al minimo. Sin embargo, el BBC acepta definir funciones multilinea, cosa que el Spectrum ni el BB3 tienen eso, tuve que convertir dichas funciones asociandolas con sus procedimientos respectivos los cuales cogen los parametros y retornan un valor a travez de una funcion. En cuanto al metodo de manejo de ficheros del BBC, los reemplace por SAVE/LOAD DATA y CODE respectivamente. Listado version BetaBasic 3.xx: 10 REM PROGRAM SYLLOGISM 20 DEF FN n$(s$,s,l)=s$(s TO ((s-1+l AND l>0)+(LEN s$ AND l<1))) 30 LET true=1,false=0 40 LET m$="I have no information on:",f$="" 60 DIM n$(5) 80 Intro 90 Initialize 100 Load_data 120 DO 130 D_Input 140 LOOP UNTIL Quit 150 Save_data 160 END 210 DEF PROC Intro 220 CLS 230 PRINT "SYLLOGISM ANALYZER" 250 PRINT '''"Press to continue" 260 INPUT USR 1415 270 CLS 280 PRINT " You may converse with this program" 290 PRINT "using normal (though limited)" 300 PRINT TAB 10;"English sentences." 310 PRINT '" Type facts in the form:" 320 PRINT f$;" IS ";f$;"." 330 PRINT "where the full-stop is optional" 340 PRINT '" Ask questions in the form:" 350 PRINT "IS ";f$;", ";f$;"?" 360 PRINT "where the '?' is complusory, and" 370 PRINT " the second noun phrase must start" 380 PRINT "with 'A', 'AN' or 'THE'." 390 PRINT '"Sentences are typed after the" 400 PRINT "'?' prompt. Use upper-case to" 410 PRINT "avoid confusion." 420 PRINT "Type 'QUIT' to terminate input." 430 PRINT '"Press to continue" 440 INPUT USR 1415 450 END PROC 470 DEF PROC Initialize 490 CLS 500 LET Quit=FALSE,Max=78 520 LET wks=1+INT (max*max/8) 540 DIM d$(max,13): LET d=0 600 LET tbl=44000,cov=45255 610 Clear tbl 630 DIM r$(8,5): DIM r(8) 640 FOR i=1 TO 8: READ s$: LET r(i)=LEN s$,r$(i)=s$: NEXT i 670 DATA "IS ","A ","AN ","THE "," IS "," A "," AN "," THE " 700 DIM e(8): FOR i=1 TO 8: READ e(i): NEXT i 740 DATA 1,2,4,8,16,32,64,128 760 END PROC 780 DEF PROC D_Input 800 DO : INPUT s$: LOOP WHILE s$="" 805 LET s$=SHIFT$(1,s$): PRINT s$ 820 IF s$="QUIT" THEN LET Quit=TRUE: ELSE IF s$(LEN s$)="?" THEN Question: ELSE Fact 840 END PROC 860 DEF PROC Fact 880 IF s$(LEN s$)="." THEN LET s$=s$( TO LEN s$-1) 900 Split 5,5 910 IF j>LEN s$ THEN PRINT "I don't understand this."'"Please could you rephras e it?": RETURN 920 PRINT "I understand." 940 Ins_dict l$: LET lo=FN y() 950 Ins_dict u$: LET up=FN y() 970 Ins_tab tbl,lo,lo 980 Ins_tab tbl,up,up 990 Ins_tab tbl,lo,up 1010 END PROC 1030 DEF PROC Question 1050 LET s$=s$( TO LEN s$-1) 1070 Split 6,8 1080 IF j>LEN s$ THEN PRINT "I don't understand the question.": RETURN 1100 LET Noinfo=FALSE,prs=d 1120 Ins_dict l$: LET lo=FN y() 1130 IF lo=max OR lo>prs THEN PRINT m$'l$: LET d=prs,Noinfo=TRUE 1140 Ins_dict u$: LET up=FN y() 1150 IF up=max OR up>prs THEN PRINT m$'u$: LET d=prs,Noinfo=TRUE 1160 IF Noinfo THEN RETURN 1180 Clear cov 1190 Search up: IF FN z() THEN PRINT "YES.": ELSE PRINT "I DON'T KNOW." 1210 END PROC 1230 DEF PROC Split lo,up 1250 FOR i=1 TO LEN s$ 1260 LET ii=INSTRING(i,s$," "): IF ii THEN LET s$=s$( TO ii)+s$(ii+2 TO ): GO TO 1260 1270 NEXT i 1280 Remove s$ 1300 LET j=1 1310 DO : LET split=FALSE 1330 FOR i=lo TO up 1340 IF FN n$(s$,j,r(i))=r$(i, TO r(i)) THEN LET l$=s$( TO j),u$=FN n$(s$, j+r(i),0), split=TRUE 1350 NEXT i 1360 LET j=j+1 1370 LOOP UNTIL split OR j>LEN s$ 1390 Remove l$ 1400 Remove u$ 1420 END PROC 1440 DEF PROC Remove REF n$ 1460 DO : LET rmvd=FALSE 1480 FOR i=1 TO 8 1490 IF n$( TO r(i))=r$(i, TO r(i)) THEN LET n$=n$(r(i) TO ),rmvd=TRUE 1500 IF n$(1)=" " THEN LET n$=n$(2 TO ),rmvd=TRUE 1510 IF n$(LEN n$)=" " THEN LET n$=n$( TO LEN n$-1),rmvd=TRUE 1520 NEXT i 1530 LOOP UNTIL NOT rmvd 1550 END PROC 1570 DEF PROC Ins_dict,n$ 1590 LET d$(d+1)=n$ 1610 LET i=0 1630 DO : LET i=i+1: LOOP UNTIL d$(i, TO LEN n$)=n$ 1670 IF i=max THEN PRINT "No dictionary room for:"'n$: ELSE IF i>d THEN LET d=i 1690 DEF FN y()=i: END PROC 1710 DEF PROC Calc 1720 LET z=max*x+y,x=INT (z/8) 1730 LET y=MOD(z,8): IF y<1 THEN LET y=1 1740 END PROC 1760 DEF PROC Ins_tab,b,x,y 1780 Calc 1790 POKE b+x,OR(PEEK b+x,e(y)) 1800 END PROC 1820 DEF PROC Get_value,b,x,y: LOCAL gv 1830 Calc 1840 LET gv=-INT (AND(PEEK b+x,e(y))/e(y)) 1850 DEF FN g()=gv: END PROC 1860 DEF PROC Clear,b 1880 POKE b,STRING$(wks,CHR$ 0) 1920 END PROC 1940 DEF PROC Search,fr 1950 DEF FN z()=sh: LOCAL i,sh,fng,fnc 1970 IF fr=lo THEN LET sh=TRUE 1980 LET i=0 1990 Get_value tbl,i,fr: LET fng=FN g(): Get_value cov,i,fr: LET fnc=FN g() 2000 IF fng AND NOT fnc THEN Ins_tab cov,i,fr: Search i: IF FN z() THEN LET sh=TRUE 2010 IF i"Y" THEN GO TO 2070 2260 PRINT '"Loading dictionary..." 2280 LOAD "s_dict.$" DATA d$(): LOAD "s_tbl.b"CODE 2460 PRINT '"INPUT COMPLETE" 2470 PAUSE 100: CLS 2490 END PROC 2510 DEF PROC Save_data 2530 CLS 2540 INPUT " Do you want to save the data? (Y/N) ";A$ 2550 IF A$="N" THEN RETURN : ELSE IF A$<>"Y" THEN GO TO 2540 2580 GET W$ 2600 PRINT "Saving dictionary..." 2610 SAVE "s_dict.$" DATA d$(): SAVE "s_tbl.b"CODE tbl,wks 2680 PRINT '"FINISHED SAVING DATA" 2770 END PROC 9999 DEF PROC END CONVERSION A FICHEROS Quien observe el programa, vera que use solamente los comandos de cinta SAVE y LOAD, pero si se adapta a Microdrive, Opus u otro sistema de disco, puede cambiar los procedimientos de cinta por las rutinas OPEN-CLOSE correspondientes a tales sistemas. CONVERSION A BB4 Desconozco si les ha pasado a otros pero las versiones de BB4 que tengo, no admiten ENPROC para cada procedimiento a menos que solo sea uno. En este caso debo tipear RETURN: ENDPROC o solamente RETURN y usar nada mas que ENDPROC al final de todos los procedimientos indicando asi que ya no hay mas despues. CONVERSION A BB 1.8 No es de hecho imposible convertirlo a BB 1.8 y 1.9, en este caso las lineas 80 al 160 se verian ahora: 80 PROC Intro 90 PROC Initialize 100 PROC Load_data 120 DO 130 PROC D_Input 140 LOOP UNTIL Quit 150 PROC Save_data 160 GOTO 10000: REM eliminar linea 9999 Debido a que el BB 1.8 no acepta parametros, la alternativa seria reemplazar todos estos por variables globales pero dandoles nombres distintivos para que se sepa que procedimientos son los que invocan o requieren dichos valores. Ejemplos de algunos cambios a hacer: 940 LET w$=l$: PROC Ins_dict: LET lo=FN y() 970 LET ITBL=tbl,ITX=lo,ITY=lo: PROC Ins_tab 1180 LET covered= cov: PROC Clear CONVERSION A 48K, 128K Y +3 Debido a que un Spectrum sin extension carece de procedimientos, estos tienen que ser por fuerza convertidos a subrutinas. La conversion previa a BB 1.8 nos da ya una idea de como hacerlo. Lo primero sera tratar de mantener la misma estructura del listado base. Para ello y sabiendo en que linea empieza cada procedimiento, crearemos una lista de variables que sirvan de etiquetas labels para cada subrutina con lo que el inicio acabaria viendose asi: 22 LET intro=210:LET initialize=470:LET loaddata=2050:LET dinput=780: LET savedata=2510:LET fact=860:LET question=1030 24 LET procsplit=1230:LET remove=1440:LET insdict=1570:LET instab=1710: LET getval=1800:LET clr=1860:LET search=1940 26 LET calc=1710:LET end=20000 80 GOSUB Intro 90 GOSUB Initialize 100 GOSUB Loaddata 120 REM 130 GOSUB DInput 140 IF NOT Quit THEN GOTO 120 150 GOSUB Savedata 160 GOTO END Y lo mismo con las otras lineas: 940 LET w$=l$: GOSUB Insdict: LET lo=FN y() 970 LET ITBL=tbl,ITX=lo,ITY=lo: GOSUB Instab 1180 LET covered= cov: GOSUB Clear 2510 REM SUBR. Savedata Por ultimo, reemplazar todos los bucles DO-LOOP por IF GOTO Y eliminar la linea con SHIFT$ e incluir POKE 23658,8 al listado, para que todo sea tipeado en mayusculas. Y debido a la falta de INSTRING, debemos modificar la linea para que se vea: 1260 IF FN n$(s$,i,2)=" " THEN LET s$=s$(TO ii)+s$(ii+2 TO): GO TO 1260 Y la linea: 1880 FOR i=0 TO wks: POKE b+i,0: NEXT i Otro detalle, debido a que el 128k y +3 no aceptan palabras reservadas como nombre de variable, en casos como Clear habra que cambiarlo a CLR ya que no existe en el Spectrum y asi sucesivamente. Otro detalle a notar BB3 permite crear procedimientos y variables con el mismo nombre, por lo que en el caso de split debo diferenciarlo asi que dejo split como variable y al proc. lo renombre procsplit. CONVERSION A SAM En este caso se puede usar el listado del BB3 sin mas cambios que retener la funcion MID$, eliminar la linea con SHIFT$ y dejar todo en modo mayusculas. En cuanto a la linea 1260, se puede usar INSTR o MID$ indistintamente. En cuanto a END podemos usar ya sea LABEL o LET para su definicion y uso con GOTO si es que queremos tenerla en el listado. Clear debe ser renombrado a CLR. CONVERSION A QL Considerando que el Super Basic es plenamente estructurado y posee tanto procedimientos como la definicion de funciones multilinea, solamente hay que cambiar todo de acuerdo con su sintaxis. Y al igual que con SAM definir MID$ e ignorar SHIFT$. Y eso seria todo en cuanto a como convertir el listado al Spectrum y afines. (c)2023 zx_if1@hotmail.com