La ricorsione in Basic su Commodore 64 – La Torre di Hanoi

15 Set , 2024 - programmazione

La ricorsione in Basic su Commodore 64 – La Torre di Hanoi

Ma è possibile scrivere un programma in Basic per il Commodore 64 che sfrutti la tecnica della ricorsione ? Oggi parleremo di programmazione Basic per il commodore 64 e di ricorsione e per farlo prenderemo a prestito il famoso gioco della torre di Hanoi, uno dei più famosi algoritmi che si insegna nelle scuole che fa uso della tecnica della ricorsione è proprio quello che risolve il problema dell’enigma della torre di Hanoi.

Oggi realizzerò per te tre programmi.

Nella prima parte del video quindi ti farò vedere come realizzare  un motore grafico per giocare manualmente alla torre di Hanoi potrai quindi impratichirti e anche a divertirti.

Nella seconda parte del video invece andrò a scrivere un programma che risolve l’enigma della torre di Hanoi sfruttando la tecnica della ricorsione.

Infine nella terza e ultima parte unirò i due programmi creandone uno unico che ti permetterà sia di giocare sia di vedere risolto.

Puoi trovare sorgenti da scaricare dia in formato .D64 sia in formato “CBM prg Studio” (.cbmprj)

Clicca qui per scaricarle il formato .D64: hanoi-tower.d64

hanoi-tower.d64

Nota importante: il programma per poter funzionare necessita lo spostamento della memoria dell’interprete basic

Il modo più rapido e indolore per caricare correttamente il codice di hanoi.bas in un emulatore come VICE, è trascinare il file .D64 direttamentre sul programma di emulazione C64 “VICE”. Verrà avviato il caricamento con il classico

LOAD “*”,8,1

il quale comando caricherà il file LOADER.BAS che poi caricherà HANOI.BAS

Il alternativa bisogna prima dare i comandi:

poke 43,1:poke 44,64:poke 16384,0

e poi caricare il programma “HANOI” con ,8 e non con ,8,1

Clicca qui per scaricarle il formato CBM prg Studio (.cbmprj): hanoi(CBM-prg-Studio).7z

La base del programma: l’algoritmo ricorsivo

All’interno dei sorgenti troverai un programma in basic denominato hanoi recursion.bas che implementa la base dell’algoritmo ricorsivo come spiegato nel video.

Questo programma non ha le animazioni grafiche ma solo stampa a video in modo testuale la soluzione delle mosse da fare per risolvere l’enigma .

10 A=1:B=2:C=3:print chr$(147)
20 input "quanti dischi";D:print "si risolve con "2^D-1" mosse{down}"
30 N=D:SP=49151:PRINT "inizio sp="SP:M=0
40 REM SALVO LE VARIABILI NELLO STACK A PARTIRE DALLA LOCAZIONE 49152:
50 SP=SP+1:POKE SP,N:SP=SP+1:POKE SP,A:SP=SP+1:POKE SP,B:SP=SP+1:POKE SP,C
60 GOSUB 80:REM 1a CHIAMATA  Hanoi($n, $a, $b ,$c);
70 PRINT "fine sp="SP:END

80 if N>1 then 150:REM RAMO1:E' COME DIRE IF N=1 ALLORA EESGUI LE RIGHE SEGUENTI
90 M=M+1:PRINT "ramo 1 mossa"M": muovi #" A " -> #" C
100 REM RITORNO DALLA RICORSIONE,RIPRISTINO LE VARIABILI DALLO STACK
110 C=PEEK(SP):SP=SP-1:B=PEEK(SP):SP=SP-1:A=PEEK(SP):SP=SP-1:N=PEEK(SP):SP=SP-1
120 REM PRINT "ritorno dalla ricorsione ramo 1"
130 RETURN

140 REM ELSE (N>1): RAMO 2
150 N=N-1
160 REM SALVO LE VARIABILI NELLO STACK:
170 SP=SP+1:POKE SP,N:SP=SP+1:POKE SP,A:SP=SP+1:POKE SP,B:SP=SP+1:POKE SP,C
180 X=B:B=C:C=X:REM SCAMBIO B CON C  Hanoi($n, $a, $c ,$b);
190 GOSUB 80
200 M=M+1:PRINT "ramo 2 mossa"M": muovi #" A " -> #" C
210 REM SALVO LE VARIABILI NELLO STACK:
220 SP=SP+1:POKE SP,N:SP=SP+1:POKE SP,A:SP=SP+1:POKE SP,B:SP=SP+1:POKE SP,C
230 X=A:A=B:B=X:REM SCAMBIO A CON B  hanoi($n, $b, $a ,$c);
240 GOSUB 80
250 REM RITORNO DALLA RICORSIONE,RIPRISTINO LE VARIABILI DALLO STACK
260 C=PEEK(SP):SP=SP-1:B=PEEK(SP):SP=SP-1:A=PEEK(SP):SP=SP-1:N=PEEK(SP):SP=SP-1
270 REM PRINT "ritorno dalla ricorsione ramo 2"
280 RETURN

Il programma completo

Il programma completo con le animazioni grafiche e i suoni è invece hanoi.bas

Il gioco è stato migliorato e ripubblicato il giorno 15 Agosto 2026 con iseguenti miglioramenti:

  • giocabile non più da tastiera ma con JOYSTICK IN PORTA 2
  • modificati leggermente gli sprites
  • aggiunto effetto sonoro

ecco il codice completo:

!--------------------------------------------------
!- sabato 15 agosto 2026 17:50:39
!- Import of : HANOI.PRG
!- From Disk : c:\users\alessandro\documents\d64\hanoi-tower.d64
!- Commodore 64
!--------------------------------------------------
10 rem ***************     la torre di hanoy        ***************
20 rem ***************   by alessandro scola 2024   ***************
30 rem ***************   www.alessandroscola.com    ***************
40 rem ************************************************************************
50 rem ********************    variabili  principali  *************************
60 rem sd       :sprite definiti (si/no)
70 rem dm       :numero dichi massimi che il programma gestisce
80 rem d        :numero dischi scelti dal giocatore per la partita
90 rem mm       :numero mosse minime per vincere = 2^d-1
100 rem pi       :piolo iniziale selezionato
110 rem pf       :piolo finale selezionato
120 rem pc       :piolo corrente (selettore piolo da joystick)
130 rem p1       :peso disco in alto su piolo 1
140 rem p2       :peso disco in alto su piolo 2
150 rem p3       :peso disco in alto su piolo 3
160 rem p1(dm)   :situazione pesi dischi su piolo 1
170 rem p2(dm)   :situazione pesi dischi su piolo 2
180 rem p3(dm)   :situazione pesi dischi su piolo 3
190 rem q1,q2,q3 :numero dischi presenti su ogni piolo
200 rem x1,x2,x3 :coordinate x degli sprites su ogni piolo
210 rem y0       :coordinata y minima sprites (il punto piu in alto)
220 rem y9       :coordinata y massima sprites (il punto piu in basso)
230 rem ad       :altezza sprite di un singolo disco in pixels
240 rem sn       :sprite number
250 rem sp       :stack pointer (per la soluzione ricorsiva)
260 rem v        :registro del vic di partenza per gestion sprites
270 rem b        :banco memoria di partenza per gli sprite
280 rem ************************************************************************
290 rem ************************************************************************
300 sd=0:rem sprites non ancora definiti
310 dm=8:rem fino a 8 dischi massimo
320 dim p1(dm):rem stato presenza dei pioli su piolo 1, da 1 a 7
330 dim p2(dm):rem stato presenza dei pioli su piolo 2, da 1 a 7
340 dim p3(dm):rem stato presenza dei pioli su piolo 3, da 1 a 7
350 x1=76:x2=156:x3=236:rem coordinate x degli sprites su pioli
360 y0=60:rem y mimina (punto piu in alto quando muovo disco)
370 y9=168:rem y massima (coord y pputno di appoggio dei dischi al piano)
380 ad=12:rem altezza disco in pixels(sprite espanso =6 x 2 = 12)
390 v=53248:rem registro del vic di partenza per gestion sprites
400 rem ************************************************************************
410 poke 53280,15:poke 53281,0:poke 646,1:rem colore sfondo,bordo scritte
420 poke 53269,0:rem spegne tutti gli sprites eventualmente visibili
430 if peek(44)=64 then 520
440 print "{clear}attenzione!!"
450 print "{down}per eseguire questo programma"
460 print "devi prima eseguire il seguente comando:"
470 print "{down}{red}poke 43,1:poke 44,64:poke 16384,0{down*2}"
480 print "{white}poi ricarica il programma da disco"
490 print "con ,8 e non con ,8,1{space*3}!! "
500 print "{down}alla fine eseguilo con il comando run"
510 end
520 rem ***********************************************************************
530 print "{clear}"spc(9)"{down*3}{red}la{space*2}torre{space*2}di{space*2}hanoi"
540 print spc(6)"{down*4}{cyan}by alessandro scola (c)2024"
550 print spc(8)"{white}www.alessandroscola.com"
560 print spc(6)"{down*2}{blue}gioca alla torre di hanoi"
570 print spc(6)"o{space*2}falla risolvere al tuo"
580 print spc(6)"commodore 64 con il metodo"
590 print spc(6)"ricorsivo."
600 if sd=1 goto 730
610 rem ***************************
620 rem * ridefinisce gli sprites *
630 rem ***************************
640 print "{down*4}{yellow}{space*2}inizializzazione sprites, attendi..."
650 b=245:rem banco memoria di partenza per gli sprite 245
660 rem legge i data per i dischi che utilizzero
670 for sn=0 to dm-1
680 poke 1862,56-sn:rem visualizza conto alla rovescia
690 poke 2040+sn,b+sn:rem setta banco di memoria per ogni sprite
700 for i=0 to 62
710 read a:poke 64*b+(sn*64)+i,a:next i
720 next sn
730 sd=1:rem sprites definiti
740 print "{yellow}{up*3}""
750 PRINT "{yellow}{home}{down*20}{space*3}premi fire in porta 2 per giocare{space*3}"
760 IF(PEEK(56320) AND 16)=0 GOTO 780:REM ATTENTE PRESSIONE FIRE
770 GOTO 760
780 POKE 53269,0:POKE 53280,15:POKE 53281,0:POKE 646,1:REM COLORE SFONDO,BORDO SCRITTE
790 D=3:PRINT"{clear}{down*11}{right*9}{green}quanti dischi ? (1-8)"
800 PRINT "{yellow}{right*11}{down*3}(joystick up/down)"
810 PRINT"{home}{down*11}{right*31}{space*2}<{up}"
820 PRINT"{home}{down*10}":PRINT TAB(31);D:J=PEEK(56320)
830 J=PEEK(56320)
840 IF((J AND 1)<>0 AND (J AND 2)<>0  AND (J AND 16)<>0) GOTO 830
850 IF(D<=7 AND (J AND 1)=0) THEN D=D+1
860 IF(D>=2 AND (J AND 2)=0) THEN D=D-1
870 IF(J AND 16)=0 THEN 910
880 FOR I=1 TO 50:NEXTI:GOTO 820
890 REM FOR I=1 TO 25:NEXT I
900 POKE 56320,255:GOTO 820
910 GM$="g":PRINT "{clear}"
920 POKE 56320,255
930 IF(GM$="g") THEN PRINT"{home}{down*9}{space*11}{yellow}>{reverse on}{space*4}giocare{space*5}{reverse off}<"
940 IF(GM$="g") THEN PRINT"{home}{down*11}{space*11}{green}>vedere soluzione<"
950 IF(GM$="s") THEN PRINT"{home}{down*9}{space*11}{green}>{space*4}giocare{space*5}<"
960 IF(GM$="s") THEN PRINT"{home}{down*11}{space*11}{yellow}>{reverse on}vedere soluzione{reverse off}<"
970 PRINT "{yellow}{right*11}{down*3}(joystick up/down)"
980 POKE 56320,255:J=PEEK(56320)
990 IF(GM$="s" AND (J AND 1)=0) THEN GM$="g":GOTO 920
1000 IF(GM$="g" AND (J AND 2)=0) THEN GM$="s":GOTO 920
1010 IF(J AND 16)=0 THEN 1040
1020 FOR I=1 TO 50:NEXT I
1030 GOTO 980
1040 REM
1050 REM MEMORIZZA IN UN ARRAY LO STATO PRESENZA DISCHI PESATI SU PIOLO 1
1060 FOR I=1 TO D:P1(I)=I:NEXT I
1070 P1=1:P2=0:P3=0:REM PESO DEL DISCO IN ALTO SU UN DATO PIOLO
1080 Q1=D:Q2=0:Q3=0:REM Q1, Q2, Q3 = QUANTI DISCHI HA CIASCUN PIOLO
1090 REM POSIZIONA GLI SPRITES DEI DISCHI UNO SULL'ALTRO SU PIOLO 1
1100 REM DISEGNA LA BASE DEL GIOCO
1110 I=0:REM VARIABILE OFFSET RESGISTRI SPRITES
1120 OC=0: REM OFFFSET COLORE PER SALTARE IL NUMERO 8
1130 FOR SN=D-1 TO 0 STEP -1:REM SETTA POSIZIONE X E Y DISCHI
1140 POKE V+(SN*2),X1:I=I+1:POKE V+((SN*2)+1),Y9-((I-1)*AD/2)
1150 I=I+1
1160 IF (SN+4)=7 THEN OC=1:REM PER SALTARE IL COLORE GIALLO
1170 POKE 53287+SN,SN+4-OC:REM SETTA I COLORI DEI DISCHI
1180 NEXT SN
1190 REM ABILITA SPRITES E ESPANDILI IN LARGHEZZA E ALTEZZA
1200 VA=0:FOR N=0 TO D-1:VA=VA+(2^N):NEXT
1210 POKE 53269,VA:REM ABILITA SPRITES
1220 POKE 53277,VA:REM ESPANSIONE IN LARGHEZZA
1230 POKE 53271,VA:REM ESPANSIONE IN ALTEZZA
1240 REM *************************************************
1250 REM *************************************************
1260 MM=2^D-1:M=1:REM MM=NUMERO MOSSE MINIME X RISOLVERE, M=NUMERO MOSSA
1270 REM SPOSTA IL DISCO PIU IN ALTO DAL PIOLO SELEZIONATO
1280 PRINT "{clear}{cyan}si risolve in "+STR$(MM)+" mosse.{white}"
1290 POKE 646,1:POKE 53280,15:PRINT "{home}{cyan}si risolve in "+STR$(MM)+" mosse.{white}"
1300 GOSUB 3880:REM DISEGNA I PIOLI E LA BASE
1310 IF GM$="s" THEN 3990
1320 REM GM$="g" GIOCARE
1330 PI=0:PF=0:PC=1:REM PIOLO INIZIO,FINE,CORRENTE
1340 POKE 646,1:POKE 214,2:SYS 58732:PRINT "fai la mossa n."+STR$(M)
1350 POKE56145,1:POKE56155,1:POKE56165,1
1360 PI=0:PF=0:REM PIOLO INIZIO,FINE
1370 IF(PC=1) THEN POKE 1872,62:POKE1874,60
1380 IF(PC=1) THEN POKE 1882,32:POKE1884,32
1390 IF(PC=1) THEN POKE 1892,32:POKE1894,32
1400 IF(PC=1) THEN POKE 1919,32:POKE1927,32
1410 IF(PC=2) THEN POKE 1872,32:POKE1874,32
1420 IF(PC=2) THEN POKE 1882,62:POKE1884,60
1430 IF(PC=2) THEN POKE 1892,32:POKE1894,32
1440 IF(PC=2) THEN POKE 1919,32:POKE1927,32
1450 IF(PC=3) THEN POKE 1872,32:POKE1874,32
1460 IF(PC=3) THEN POKE 1882,32:POKE1884,32
1470 IF(PC=3) THEN POKE 1892,62:POKE1894,60
1480 IF(PC=3) THEN POKE 1919,32:POKE1927,32
1490 IF(PC=4) THEN POKE 1872,32:POKE1874,32
1500 IF(PC=4) THEN POKE 1882,32:POKE1884,32
1510 IF(PC=4) THEN POKE 1892,32:POKE1894,32
1520 IF(PC=4) THEN POKE 1919,62:POKE1927,60
1530 J=PEEK(56320)
1540 IF((J AND 4)<>0 AND (J AND 8)<>0 AND (J AND 16)<>0) AND (J AND 2)<>0 AND (J AND 1)<>0 GOTO 1530
1550 IF(J AND 4)=0 AND PC>1 THEN PC=PC-1:REM JOY A SINISTRA
1560 IF(J AND 8)=0 AND PC<3 THEN PC=PC+1:REM JOY A DESTRA
1570 IF(J AND 2)=0 THEN PC=4:REM GIU
1580 IF(J AND 1)=0 THEN PC=2:REM SU
1590 IF(J AND 16)=0 AND PC=1 AND PI=0 THEN PI=1:GOSUB 5250:GOTO1670:REM SELEZIONO P1
1600 IF(J AND 16)=0 AND PC=1 AND PI=1 THEN PI=0:GOSUB 5250:REM DESELEZIONO P1
1610 IF(J AND 16)=0 AND PC=2 AND PI=0 THEN PI=2:GOSUB 5250:GOTO1670:REM SELEZIONO P2
1620 IF(J AND 16)=0 AND PC=2 AND PI=2 THEN PI=0:GOSUB 5250:GOTO1670:REM DESELEZIONO P2
1630 IF(J AND 16)=0 AND PC=3 AND PI=0 THEN PI=3:GOSUB 5250:GOTO1670:REM SELEZIONO P3
1640 IF(J AND 16)=0 AND PC=3 AND PI=3 THEN PI=0:GOSUB 5250:GOTO1670:REM DESELEZIONO P3
1650 IF(J AND 16)=0 AND PC=4 THEN 410
1660 IF(J AND 16)=0 AND PI<>0 AND PC<>PI THEN PF=PC:GOTO 1730
1670 IF(PI=0) THEN POKE56145,1:POKE56155,1:POKE56165,1
1680 IF(PI=0) THEN PRINT "{home}{down*4}"SPC(9)"{space*21}"
1690 IF(PI=1) THEN POKE56145,10:PRINT "{pink}{home}{down*4}"SPC(9)"da piolo 1"
1700 IF(PI=2) THEN POKE56155,10:PRINT "{pink}{home}{down*4}"SPC(9)"da piolo 2"
1710 IF(PI=3) THEN POKE56165,10:PRINT "{pink}{home}{down*4}"SPC(9)"da piolo 3"
1720 GOTO 1370
1730 IF PF=1 AND GM$="g" THEN PRINT "{pink}{home}{down*4}"SPC(20)" a piolo 1"
1740 IF PF=2 AND GM$="g" THEN PRINT "{pink}{home}{down*4}"SPC(20)" a piolo 2"
1750 IF PF=3 AND GM$="g" THEN PRINT "{pink}{home}{down*4}"SPC(20)" a piolo 3"
1760 IF PI=1 AND PF=2 AND Q1>0 AND (P2=0 OR P2>P1) THEN 1960
1770 IF PI=1 AND PF=3 AND Q1>0 AND (P3=0 OR P3>P1) THEN 2260
1780 IF PI=2 AND PF=1 AND Q2>0 AND (P1=0 OR P1>P2) THEN 2550
1790 IF PI=2 AND PF=3 AND Q2>0 AND (P3=0 OR P3>P2) THEN 2840
1800 IF PI=3 AND PF=1 AND Q3>0 AND (P1=0 OR P1>P3) THEN 3130
1810 IF PI=3 AND PF=2 AND Q3>0 AND (P2=0 OR P2>P3) THEN 3420
1820 POKE 53280,2:PRINT "{home}{down*4}{right*9}{red}* mossa non possibile *""
1830 rem for i=1 to 255:next i:for i=1 to 255:next i
1840 rem error sound
1850 s=54272:for i=0 to 24:poke s+i,0:next i:poke s+24,15
1860 poke s+1,8:poke s+0,0:rem low frequency note
1870 poke s+5,0:poke s+6,240
1880 poke s+4,65:rem pulse wave on
1890 for pw=1 to 15
1900 poke 53280,pw
1910 poke s+3,pw:poke s+2,0:rem sweep high byte of pulse width
1920 for t=1 to 40:next t
1930 next pw
1940 poke s+4,64:rem pulse off
1950 print "{home}{down*4}{right*9}{red}{space*24}":poke 53280,15:goto 1340
1960 rem ******************************************
1970 rem * spostamento disco da piolo 1 a piolo 2 *
1980 rem ******************************************
1990 rem p1 = valore del disco piu in alto,che corrisponde allo sprites p1-1
2000 for y=peek(v+1+(2*(p1-1))) to y0 step -2
2010 poke (v+1+(2*(p1-1))),y:rem sollevo disco
2020 next y
2030 for x=peek(v+(2*(p1-1))) to x2 step 2
2040 poke (v+(2*(p1-1))),x:rem sposto disco a dx
2050 next x
2060 rem appoggio disco:
2070 rem y1= coord y di partenza  y2 = coord y di arrivo dello sprite
2080 y1=peek(v+1+(2*(p1-1))):rem altrimenti y di arrivo e' appena sopra disco
2090 if p2=0 then y2=y9:goto 2110
2100 y2=y9-(ad*q2)
2110 for y=y1 to y2 step 2
2120 poke (v+1+(2*(p1-1))),y
2130 next y
2140 gosub 4300:rem riproduci suono
2150 rem aggiorno peso pila di destinazione 2
2160 for i=q2+1 to 1 step -1:p2(i)=p2(i-1):next i:rem scalo in alto i pesi
2170 p2(1)=p1:p2=p1:q2=q2+1
2180 rem aggiorno presenza dischi pila di partenza 1
2190 if q1>1 then:for i=1 to q1-1:p1(i)=p1(i+1):next i:rem scalo in basso i pesi
2200 p1(q1)=0:q1=q1-1
2210 if q1>=1 then p1=p1(1)
2220 if q1=0 then p1(1)=0:p1=0
2230 if gm$="g" then 3680
2240 print "{home}{down*4}"spc(9)"{space*21}"
2250 return
2260 rem ******************************************
2270 rem * spostamento disco da piolo 1 a piolo 3 *
2280 rem ******************************************
2290 for y=peek(v+1+(2*(p1-1))) to y0 step -2
2300 poke (v+1+(2*(p1-1))),y:rem sollevo disco
2310 next y
2320 for x=peek(v+(2*(p1-1))) to x3 step 2
2330 poke (v+(2*(p1-1))),x:rem sposto disco a dx
2340 next x
2350 rem appoggio disco:
2360 rem y1= y di partenza  y2 = y di arrivo
2370 y1=peek(v+1+(2*(p1-1)))
2380 if p3=0 then y2=y9:goto 2400
2390 y2=y9-(ad*q3):rem altrimenti y di arrivo e' appena sopra disco
2400 for y=y1 to y2 step 2
2410 poke (v+1+(2*(p1-1))),y
2420 next y
2430 gosub 4300:rem riproduci suono
2440 rem aggiorno peso pila di destinazione 3
2450 for i=q3+1 to 1 step -1:p3(i)=p3(i-1):next i:rem scalo in basso i pesi
2460 p3(1)=p1:p3=p1:q3=q3+1
2470 rem aggiorno presenza dischi pila di partenza 1
2480 if q1>1 then:for i=1 to q1-1:p1(i)=p1(i+1):next i:rem scalo in alto i pesi
2490 p1(q1)=0:q1=q1-1
2500 if q1>=1 then p1=p1(1)
2510 if q1=0 then p1(1)=0:p1=0
2520 if gm$="g" then 3680
2530 print "{home}{down*4}"spc(9)"{space*21}"
2540 return
2550 rem *******************************************
2560 rem * spostamento disco da piolo 2 a piolo 1  *
2570 rem *******************************************
2580 for y=peek(v+1+(2*(p2-1))) to y0 step -2
2590 poke (v+1+(2*(p2-1))),y:rem sollevo disco
2600 next y
2610 for x=peek(v+(2*(p2-1))) to x1 step -2
2620 poke (v+(2*(p2-1))),x:rem sposto disco a sx
2630 next x
2640 rem appoggio disco:
2650 rem y1= coord y di partenza  y2 = coord y di arrivo dello sprite
2660 y1=peek(v+1+(2*(p2-1))):rem altrimenti y di arrivo e' appena sopra disco
2670 if p1=0 then y2=y9:goto 2690
2680 y2=y9-(ad*q1)
2690 for y=y1 to y2 step 2
2700 poke (v+1+(2*(p2-1))),y
2710 next y
2720 gosub 4300:rem riproduci suono
2730 rem aggiorno peso pila di destinazione 1
2740 for i=q1+1 to 1 step -1:p1(i)=p1(i-1):next i:rem scalo in basso i pesi
2750 p1(1)=p2:p1=p2:q1=q1+1
2760 rem aggiorno presenza dischi pila di partenza 2
2770 if q2>1 then:for i=1 to q2-1:p2(i)=p2(i+1):next i:rem scalo in alto i pesi
2780 p2(q2)=0:q2=q2-1
2790 if q2>=1 then p2=p2(1)
2800 if q2=0 then p2(1)=0:p2=0
2810 if gm$="g" then 3680
2820 print "{home}{down*4}"spc(9)"{space*21}"
2830 return
2840 rem *******************************************
2850 rem * spostamento disco da piolo 2 a piolo 3  *
2860 rem *******************************************
2870 for y=peek(v+1+(2*(p2-1))) to y0 step -2
2880 poke (v+1+(2*(p2-1))),y:rem sollevo disco
2890 next y
2900 for x=peek(v+(2*(p2-1))) to x3 step 2
2910 poke (v+(2*(p2-1))),x:rem sposto disco a sx
2920 next x
2930 rem appoggio disco:
2940 rem y1= coord y di partenza  y2 = coord y di arrivo dello sprite
2950 y1=peek(v+1+(2*(p2-1))):rem altrimenti y di arrivo e' appena sopra disco
2960 if p3=0 then y2=y9:goto 2980
2970 y2=y9-(ad*q3)
2980 for y=y1 to y2 step 2
2990 poke (v+1+(2*(p2-1))),y
3000 next y
3010 gosub 4300:rem riproduci suono
3020 rem aggiorno peso pila di destinazione 3
3030 for i=q3+1 to 1 step -1:p3(i)=p3(i-1):next i:rem scalo in basso i pesi
3040 p3(1)=p2:p3=p2:q3=q3+1
3050 rem aggiorno presenza dischi pila di partenza 2
3060 if q2>1 then:for i=1 to q2-1:p2(i)=p2(i+1):next i:rem scalo in alto i pesi
3070 p2(q2)=0:q2=q2-1
3080 if q2>=1 then p2=p2(1)
3090 if q2=0 then p2(1)=0:p2=0
3100 if gm$="g" then 3680
3110 print "{home}{down*4}"spc(9)"{space*21}"
3120 return
3130 rem ******************************************
3140 rem * spostamento disco da piolo 3 a piolo 1 *
3150 rem ******************************************
3160 for y=peek(v+1+(2*(p3-1))) to y0 step -2
3170 poke (v+1+(2*(p3-1))),y:rem sollevo disco
3180 next y
3190 for x=peek(v+(2*(p3-1))) to x1 step -2
3200 poke (v+(2*(p3-1))),x:rem sposto disco a dx
3210 next x
3220 rem appoggio disco:
3230 rem y1= y di partenza  y2 = y di arrivo
3240 y1=peek(v+1+(2*(p3-1)))
3250 if p1=0 then y2=y9:goto 3270
3260 y2=y9-(ad*q1):rem altrimenti y di arrivo e' appena sopra disco
3270 for y=y1 to y2 step 2
3280 poke (v+1+(2*(p3-1))),y
3290 next y
3300 gosub 4300:rem riproduci suono
3310 rem aggiorno peso pila di destinazione 1
3320 for i=q1+1 to 1 step -1:p1(i)=p1(i-1):next i:rem scalo in basso i pesi
3330 p1(1)=p3:p1=p3:q1=q1+1
3340 rem aggiorno presenza dischi pila di partenza 3
3350 if q3>1 then:for i=1 to q3-1:p3(i)=p3(i+1):next i:rem scalo in alto i pesi
3360 p3(q3)=0:q3=q3-1
3370 if q3>=1 then p3=p3(1)
3380 if q3=0 then p3(1)=0:p3=0
3390 if gm$="g" then 3680
3400 print "{home}{down*4}"spc(9)"{space*21}"
3410 return
3420 rem ******************************************
3430 rem * spostamento disco da piolo 3 a piolo 2 *
3440 rem ******************************************
3450 for y=peek(v+1+(2*(p3-1))) to y0 step -2
3460 poke (v+1+(2*(p3-1))),y:rem sollevo disco
3470 next y
3480 for x=peek(v+(2*(p3-1))) to x2 step -2
3490 poke (v+(2*(p3-1))),x:rem sposto disco a sx
3500 next x
3510 rem appoggio disco:
3520 rem y1= y di partenza  y2 = y di arrivo
3530 y1=peek(v+1+(2*(p3-1)))
3540 if p2=0 then y2=y9:goto 3560
3550 y2=y9-(ad*q2):rem altrimenti y di arrivo e' appena sopra disco
3560 for y=y1 to y2 step 2
3570 poke (v+1+(2*(p3-1))),y
3580 next y
3590 gosub 4300:rem riproduci suono
3600 rem aggiorno peso pila di destinazione 2
3610 for i=q2+1 to 1 step -1:p2(i)=p2(i-1):next i:rem scalo in basso i pesi
3620 p2(1)=p3:p2=p3:q2=q2+1
3630 rem aggiorno presenza dischi pila di partenza 3
3640 if q3>1 then:for i=1 to q3-1:p3(i)=p3(i+1):next i:rem scalo in alto i pesi
3650 p3(q3)=0:q3=q3-1
3660 if q3>=1 then p3=p3(1)
3670 if q3=0 then p3(1)=0:p3=0
3680 poke56145,1:poke56155,1:poke56165,1:if gm$="s" then return
3690 print "{home}{down*4}"spc(9)"{space*21}"
3700 if q3<>d then 3850:rem ho finito il gioco (q3=d ?)
3710 rem print"{clear}":gosub 3500:poke 646,5:poke 53280,5
3720 print "{home}{space*32}":poke 646,5:poke 53280,5
3730 print"{up*24}{down}{space*3}complimenti,hai risolto il gioco!"
3740 if(m=mm) then print "{space*3}nel numero minimo di mosse ("str$(mm)")"
3750 poke 646,1:if(m<>mm) then print "{space*3}hai fatto"str$(m)" mosse su"str$(mm)" previste"
3760 print "{home}{down*4}"spc(9)"{space*21}"
3770 poke 1872,32:poke 1874,32
3780 poke 1882,32:poke 1884,32
3790 poke 1892,32:poke 1894,32
3800 poke 1919,62:poke 1927,60
3810 gosub 5060:rem victory sound
3820 if(peek(56320) and 16)=0 goto 410
3830 goto 3820
3840 print "{clear}":poke 53269,0:end
3850 m=m+1:rem incremento mosse fatte
3860 goto 1340
3870 rem disegno i pioli e la base
3880 print "{down*5}":poke 646,1
3890 for i=1 to 13
3900 print "{space*9}{reverse on} {reverse off}{space*9}{reverse on} {reverse off}{space*9}{reverse on} "
3910 next i
3920 rem print "{space*2}{reverse on}{space*36}"
3930 print "{space*2}{reverse on}{space*36}"
3940 print "{space*2}{reverse on}{space*6}{reverse off} 1 {reverse on}{space*7}{reverse off} 2 {reverse on}{space*7}{reverse off} 3 {reverse on}{space*7}"
3950 print "{space*2}{reverse on}{space*13}{reverse off} termina {reverse on}{space*14}"
3960 print "{space*2}{reverse on} sposta tutti i dischi sul piolo #3 "
3970 return
3980 rem ***********************
3990 rem * soluzione ricorsiva:*
4000 rem ***********************
4010 poke 1919,62:poke 1927,60:rem per terminare premi fuoco su >termina<
4020 n=d:sp=49151:a=1:b=2:c=3:m=0
4030 rem salvo le variabili nello stack a partire dalla locazione 49152:
4040 sp=sp+1:poke sp,n:sp=sp+1:poke sp,a:sp=sp+1:poke sp,b:sp=sp+1:poke sp,c
4050 gosub 4070:rem 1a chiamata  hanoi($n, $a, $b ,$c);
4060 goto 3700
4070 if n>1 then 4150:rem ramo1:e' come dire if n=1 esegui le righe seguenti
4080 m=m+1:a$=mid$(str$(a),2,1):b$=mid$(str$(c),2,1):pi=a:pf=c
4090 print "{home}{down*2}mossa "str$(m)": #"a$" -> #"b$:gosub 1730
4100 rem ritorno dalla ricorsione,ripristino le variabili dallo stack
4110 c=peek(sp):sp=sp-1:b=peek(sp):sp=sp-1:a=peek(sp):sp=sp-1:n=peek(sp):sp=sp-1
4120 rem print "ritorno dalla ricorsione ramo 1"
4130 return
4140 rem else (n>1): ramo 2
4150 n=n-1
4160 rem salvo le variabili nello stack:
4170 sp=sp+1:poke sp,n:sp=sp+1:poke sp,a:sp=sp+1:poke sp,b:sp=sp+1:poke sp,c
4180 x=b:b=c:c=x:rem scambio b con c  hanoi($n, $a, $c ,$b);
4190 gosub 4070
4200 m=m+1:a$=mid$(str$(a),2,1):b$=mid$(str$(c),2,1):pi=a:pf=c
4210 print "{home}{down*2}mossa "str$(m)": #"a$" -> #"b$:gosub 1730
4220 rem salvo le variabili nello stack:
4230 sp=sp+1:poke sp,n:sp=sp+1:poke sp,a:sp=sp+1:poke sp,b:sp=sp+1:poke sp,c
4240 x=a:a=b:b=x:rem scambio a con b  hanoi($n, $b, $a ,$c);
4250 gosub 4070
4260 rem ritorno dalla ricorsione,ripristino le variabili dallo stack
4270 c=peek(sp):sp=sp-1:b=peek(sp):sp=sp-1:a=peek(sp):sp=sp-1:n=peek(sp):sp=sp-1
4280 rem print "ritorno dalla ricorsione ramo 2"
4290 return
4300 rem *** suono dischi ***
4310 poke54296,15
4320 poke54277,0
4330 poke54278,240
4340 poke54272,100
4350 poke54273,20
4360 poke54276,129
4370 fort=1to20:next
4380 poke54276,128
4390 if gm$="s" and (peek(56320) and 16)=0 then 410
4400 return
4410 rem *******************
4420 rem
4430 data 0,0,0,0,0,0,0,0,0,0
4440 data 0,0,0,0,0,0,0,0,0,0
4450 data 0,0,0,0,0,0,0,0,0,0
4460 data 0,0,0,0,0,0,0,0,0,0
4470 data 0,0,0,0,0,0,247,0,1,231
4480 data 128,1,247,128,1,247,128,1,247,128
4490 data 0,255,0
4500 rem
4510 data 0,0,0,0,0,0,0,0,0,0
4520 data 0,0,0,0,0,0,0,0,0,0
4530 data 0,0,0,0,0,0,0,0,0,0
4540 data 0,0,0,0,0,0,0,0,0,0
4550 data 0,0,0,0,0,1,231,128,3,219
4560 data 192,3,247,192,3,239,192,3,195,192
4570 data 1,255,128
4580 rem
4590 data 0,0,0,0,0,0,0,0,0,0
4600 data 0,0,0,0,0,0,0,0,0,0
4610 data 0,0,0,0,0,0,0,0,0,0
4620 data 0,0,0,0,0,0,0,0,0,0
4630 data 0,0,0,0,0,3,231,192,7,219
4640 data 224,7,247,224,7,219,224,7,231,224
4650 data 3,255,192
4660 rem
4670 data 0,0,0,0,0,0,0,0,0,0
4680 data 0,0,0,0,0,0,0,0,0,0
4690 data 0,0,0,0,0,0,0,0,0,0
4700 data 0,0,0,0,0,0,0,0,0,0
4710 data 0,0,0,0,0,7,247,224,15,239
4720 data 240,15,215,240,15,195,240,15,247,240
4730 data 7,255,224
4740 rem
4750 data 0,0,0,0,0,0,0,0,0,0
4760 data 0,0,0,0,0,0,0,0,0,0
4770 data 0,0,0,0,0,0,0,0,0,0
4780 data 0,0,0,0,0,0,0,0,0,0
4790 data 0,0,0,0,0,15,199,240,31,223
4800 data 248,31,199,248,31,251,248,31,199,248
4810 data 15,255,240
4820 rem
4830 data 0,0,0,0,0,0,0,0,0,0
4840 data 0,0,0,0,0,0,0,0,0,0
4850 data 0,0,0,0,0,0,0,0,0,0
4860 data 0,0,0,0,0,0,0,0,0,0
4870 data 0,0,0,0,0,31,231,248,63,223
4880 data 252,63,199,252,63,219,252,63,231,252
4890 data 31,255,248
4900 rem
4910 data 0,0,0,0,0,0,0,0,0,0
4920 data 0,0,0,0,0,0,0,0,0,0
4930 data 0,0,0,0,0,0,0,0,0,0
4940 data 0,0,0,0,0,0,0,0,0,0
4950 data 0,0,0,0,0,63,195,252,127,251
4960 data 254,127,247,254,127,239,254,127,239,254
4970 data 63,255,252
4980 rem
4990 data 0,0,0,0,0,0,0,0,0,0
5000 data 0,0,0,0,0,0,0,0,0,0
5010 data 0,0,0,0,0,0,0,0,0,0
5020 data 0,0,0,0,0,0,0,0,0,0
5030 data 0,0,0,0,0,127,231,254,255,219
5040 data 255,255,231,255,255,219,255,255,231,255
5050 data 127,255,254
5060 rem ********* victory sound ********
5070 q=54272:for i=0 to 24:poke q+i,0:next i:poke q+24,15
5080 poke q+5,15:poke q+6,240
5090 poke q+1,25:poke q+0,243:poke q+4,17
5100 for t=1 to 50:next t
5110 poke q+4,16:for t=1 to 15:next t
5120 poke q+1,25:poke q+0,243:poke q+4,17
5130 for t=1 to 50:next t
5140 poke q+4,16:for t=1 to 15:next t
5150 poke q+1,25:poke q+0,243:poke q+4,17
5160 for t=1 to 50:next t
5170 poke q+4,16:for t=1 to 15:next t
5180 poke q+1,34:poke q+0,164:poke q+4,17
5190 for t=1 to 180:next t
5200 poke q+4,16:for t=1 to 15:next t
5210 poke q+1,51:poke q+0,230:poke q+4,17
5220 for t=1 to 350:next t
5230 poke q+4,16
5240 return
5250 rem ************ suono bleep **************
5260 poke 54296,15
5270 poke 54277,17
5280 poke 54278,150
5290 poke 54273,100
5300 poke 54272,100
5310 poke 54276,17
5320 for t=1 to 12:next t
5330 poke 54273,70
5340 poke 54272,100
5350 for t=1 to 12:next t
5360 poke 54273,40
5370 poke 54272,100
5380 for t=1 to 18:next t
5390 poke 54276,16
5400 poke 54276,0
5410 return