Robottino Wally – Laboratorio di Programmazione

saverio @ 18:32

PROGETTO PROGRAMMAZIONE: codename WALLY

Un robot, situato inizialmente in una posizione di coordinate X,Y di una matrice quadrata, può muoversi di un passo alla volta nelle quattro direzioni cardinali: nord, sud, est e ovest (v. Fig.1).

Fig. 1: Direzioni di moto

Fig. 1: Direzioni di moto

In via preliminare impostare il problema nel seguente modo: data una costante T, (che rappresenta la durata della “vita” del robot), scrivere, utilizzando un generatore casuale dei quattro possibili spostamenti elementari del robot, una procedura ricorsiva in cui il robot effettui esattamente T spostamenti sulla matrice.
Prima di procedere agli ulteriori perfezionamenti del programma definire le seguenti strutture dati e schemi di interfaccia utente:

Parametri per il setup della simulazione.
1. Dimensioni della matrice ambiente della simulazione;
2. Posizione iniziale del robot R;
3. Durata T della vita di R;

Individuato il metodo operativo in relazione al quadro generale del problema, arricchire il progetto come segue:

Prima Fase: Definire un punto di partenza e uno o più punti differenti di arrivo: scrivere una procedura che permetta al robot di spostarsi in maniera “intelligente” dal luogo in cui si trova in un luogo prefissato, continuando a decrementare di uno il valore della sua “vita” dopo ogni spostamento elementare.

Seconda Fase: Utilizzare una generazione casuale per introdurre nella matrice un certo numero K1 di ostacoli e potenziare il robot dandogli la capacità di “vedere” gli ostacoli fino a un intorno completo di raggio 2 (v. Fig. 2). Riscrivere le procedure precedenti per questo robot potenziato. NB. La procedura relativa alla Prima Fase non necessariamente deve avere successo. Dopo alcuni tentativi ragionevoli il robot potrebbe rinunciare allo scopo di raggiungere il posto prefissato.

Fig. 2: K1 ostacoli, sensore Z=2

Fig. 2: K1 ostacoli, sensore Z=2

Parametri aggiuntivi per il setup della simulazione.
4. Numero K1 di ostacoli;

Terza fase: si utilizzi ancora una generazione casuale per introdurre in K2 posizioni della matrice dei punti di ricarica per il robot. Il robot inizialmente è predisposto alla ricarica ed ha la capacità di distinguere le ricariche dagli ostacoli; se “vede” dei punti di ricarica allora, e solo allora, tenderà a spostarsi su di essi aumentando la propria autonomia, altrimenti si muoverà secondo la strategia precedentemente fissata evitando gli ostacoli.

N.B. Dopo una ricarica la sua “vita” aumenterà di un valore M prefissato, ma, per un periodo di T passi, continuerà a spostarsi verso l’obiettivo non distinguendo le ricariche dagli ostacoli.

Fig. 3: Sensori di ricarica (K2=3)

Fig. 3: Sensori di ricarica (K2=3)

Parametri aggiuntivi per il setup della simulazione.
5. Numero K2 di punti di ricarica;
6. Aumento M della vita T di R dovuto al consumo di C;

Il programma termina quando si azzera la “vita” del robot oppure l’obiettivo è stato raggiunto.

Schema di interfaccia: (facoltativo)

L’interfaccia presenterà alcuni tasti di controllo, l’ipotesi minima è la seguente:
START – STOP – PAUSE – CONTINUE – RESET
è possibile ipotizzare anche un cambiamento dei parametri in corso di simulazione, mantenendo lo stato computazionale a cui è arrivata al simulazione dopo N passi.

Fig. 4: Esempio completo

Fig. 4: Esempio completo

Memoria del robot

Si consideri che il robot possa memorizzare un numero massimo P di posizioni dove è passato o che ha ispezionato; tale memoria può essere simulata attraverso l’utilizzo di una struttura dinamica (ad esempio si potrebbe pensare ad una struttura tipo coda da gestire da parte del robot mediante una lista. L’elemento della lista può essere di tipo record con i seguenti elementi: coordinata X, coordinata Y, e tipologia della casella [O=ostacolo; C=ricarica; R=transitato; .....]. Quando il robot deve spostarsi in una nuova locazione della matrice, controlla nella lista delle ultime P posizioni se già è stato in quella posizione o se già era stata ispezionata. Se decide di spostarsi, per mantenere costante P (max 10), elimina dalla testa un record di memoria e aggiunge quello più recente in coda.

Annotazioni Finali

Il lavoro deve essere fortemente orientato all’astrazione dei dati e dei metodi, quindi gli strumenti più importanti devono essere gestiti attraverso l’uso di una o più unit che devono essere opportunamente documentate indipendentemente dalla documentazione di progetto. La quota di interfaccia con l’utente prevista dal testo sopra descritto deve essere ben progettata in modo che l’utente non abbia necessità di fare ricorso ad un manuale utente. Riassumendo devono essere consegnati su dischetto o via e-mail (evitiamo lo spreco di carta):

a) un eseguibile autoconsistente, cioè che non richieda particolari accorgimenti per essere lanciato in esecuzione (altrimenti devono essere prodotte specifiche istruzioni per l’esecuzione del programma);
b) una documentazione del progetto composta delle seguenti sezioni:
• descrizione del progetto nelle sue linee generali;
• schema p-like delle chiamate di procedura;
• documentazione delle procedure;

SOLUZIONE

Questa esercitazione è fatta in linguaggio PASCAL. Purtroppo ho smarrito laa documentazione originale, posto qui solo i file sorgenti :-(

File: WALLY.PAS

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Program Wally; 
 
Uses Memoria,RobotAdt; 
 
Var M:TipoMat;
 Dim,T,InitX,InitY:Integer;
 Arrivo:RecArrivi;
 Passi:TipoMemoria; 
 
Begin
 Writeln('PROGETTO DI PROGRAMMAZIONE 2003');
 InitRand;
 InizializzaGioco(M,InitX,InitY,Dim,T,Arrivo);
 AttivaMemoria(Passi);
 PreparaGiro(M,InitX,InitY,Dim,T,Arrivo,Passi);
 Stampa(Passi);
 Smemorizza(Passi);
 Readln;
End.

File: ROBOTADT.PAS

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
(**************************************************************************) 
 
Unit RobotAdt; 
 
(**************************************************************************) 
 
Interface 
 
Uses Memoria; 
 
Const DimMax=20;
 DimVett=5;
 Ricarica=20; {Indica il valore di ogni ricarica}
 TempoCarico=10; {Indica per quanti passi Wally dopo essersi caricato non lo far… pi—} 
 
Type RecArrivi=Record
 X,Y,Distanza:Integer;
 NuovaDestinazione:Boolean;
 NuovaX,NuovaY,NuovaDistanza:Integer;
 End; 
 
 TipoMat=Array[1..DimMax,1..DimMax] Of Char;
 TipoArrivi=Array[1..DimVett] Of RecArrivi;
 TipoVista=Array[1..5,1..5] Of Char; 
 
(**************************************************************************)
Procedure InitRand; 
 
Procedure InizializzaGioco(Var M:TipoMat;Var InitX,InitY,Dim,T:Integer;Var Arrivo:RecArrivi); 
 
Procedure PreparaGiro(Var M:TipoMat;Var InitX,InitY:Integer;Dim,T:Integer;Var Arrivo:RecArrivi;Var Passi:TipoMemoria);
(**************************************************************************) 
 
Implementation 
 
Procedure InitRand; {Inizializza il generatore casuale}
Var Dep,I,RanSeed,Temp:Integer;
 Begin
 Randomize;
 Temp:=Random(10000); {Temp Š il seme}
 RanSeed:=Trunc(Temp);
 Temp:=Random(100);
 For I:=1 To Trunc(Temp) Do
 Dep:=Random(4);
 End; 
 
Function Casuale:Integer; {Assume valori da 0 a 3}
Var Temp:Integer;
 Begin
 Temp:=Random(40000);
 Casuale:=abs(Trunc(Temp/10000));
 End; 
 
Function CasualeDim(Dim:Integer):Integer; {Assume valori da 1 a Dim-2}
Var Temp:Integer;
 Begin
 Temp:=Random(40000);
 CasualeDim:=(Temp MOD Dim-1)+1;
 End; 
 
Procedure InizializzaGioco(Var M:TipoMat;Var InitX,InitY,Dim,T:Integer;Var Arrivo:RecArrivi);
Var NumArrivi,I,J,TempX,TempY:Integer;
 Vett:TipoArrivi;
 Begin
 {Setta la dimensione della matrice}
 Write('Inserisci la dimensione dell''area di gioco (Min. 2-Max. ',DimMax-2,'):');
 Readln(Dim);
 Dim:=Dim+2; {Vanno considerate due dimensioni in pi—, usate per la cornice}
 {Crea la matrice}
 For I:=2 To Dim-1 Do
 Begin
 M[1,I]:=Chr(196);
 M[Dim,I]:=Chr(196);
 M[I,1]:=Chr(179);
 M[I,Dim]:=Chr(179);
 For J:=2 To Dim-1 Do
 Begin
 M[I,J]:=' '
 End
 End;
 M[1,1]:=Chr(218);
 M[Dim,1]:=Chr(192);
 M[1,Dim]:=Chr(191);
 M[Dim,Dim]:=Chr(217);
 {Setta la vita del robot}
 Write('Inserire l''autonomia di Wally:');
 Readln(T);
 {Setta le coordinate iniziali}
 Write('Inserisci la coordinata x (min. 1, max. ',Dim-2,') di partenza di Wally:');
 Readln(InitX);
 InitX:=InitX+1; {Viene incrementata di 1 perchŠ la prima riga Š occupata dalla cornice}
 Write('Inserisci la coordinata y (min. 1, max. ',Dim-2,') di partenza di Wally:');
 Readln(InitY);
 InitY:=InitY+1; {Viene incrementata di 1 perchŠ la prima colonna Š occupata dalla cornice}
 {Setta le coordinate degli arrivi e calcola il pi— vicino}
 Write('Quanti punti d''arrivo inserire (max. ',DimVett,')?: ');
 Readln(NumArrivi);
 If NumArrivi > 0 Then
 Begin
 For I:=1 To NumArrivi Do
 Begin
 Write('Inserisci la coord. x (min. 1, max. ',Dim-2,') della destinazione num. ',I,':');
 Readln(Vett[I].X);
 Vett[I].X := Vett[I].X + 1;
 Write('Inserisci la coord. y (min. 1, max. ',Dim-2,') della destinazione num. ',I,':');
 Readln(Vett[I].Y);
 Vett[I].Y := Vett[I].Y + 1;
 Vett[I].Distanza:=Abs(InitX-(Vett[I].X))+Abs(InitY-(Vett[I].Y));
 M[(Vett[I].X),(Vett[I].Y)]:='D';
 End;
 Arrivo:=Vett[1];
 For I:=2 To NumArrivi Do {Trova verso quale punto d'arrivo dirigersi (quello che si raggiunge col minor numero di passi)}
 Begin
 If (Arrivo.Distanza)>(Vett[I].Distanza) Then
 Arrivo:=Vett[I];
 End;
 Arrivo.NuovaDestinazione:=False;
 Arrivo.NuovaX:=MaxInt;
 Arrivo.NuovaY:=MaxInt;
 Arrivo.NuovaDistanza:=MaxInt;
 End
 Else
 Begin
 Arrivo.Distanza:=MaxInt;
 Arrivo.X:=MaxInt;
 Arrivo.Y:=MaxInt;
 Arrivo.NuovaDestinazione:=False;
 Arrivo.NuovaX:=MaxInt;
 Arrivo.NuovaY:=MaxInt;
 Arrivo.NuovaDistanza:=MaxInt;
 End;
 {Setta gli ostacoli}
 Write('Quanti ostacoli inserire?:');
 Readln(J);
 I:=1;
 While I<=J Do
 Begin
 TempX:=CasualeDim(Dim);
 TempY:=CasualeDim(Dim);
 If M[TempX,TempY]=' ' Then
 Begin
 I:=I+1;
 M[TempX,TempY]:='O';
 End;
 End;
 {Setta le ricariche}
 Write('Quanti ricariche inserire?:');
 Readln(J);
 I:=1;
 While I<=J Do
 Begin
 TempX:=CasualeDim(Dim);
 TempY:=CasualeDim(Dim);
 If M[TempX,TempY]=' ' Then
 Begin
 I:=I+1;
 M[TempX,TempY]:='R';
 End;
 End;
 End; 
 
Procedure Visualizza(M:TipoMat;Dim:Integer);
Var I,J:Integer;
 Begin
 For I:=1 to Dim Do
 Begin
 For J:=1 to Dim Do
 Write(M[I,J]);
 Writeln;
 End;
 Writeln;
 End; 
 
Function Consentita(Var M:TipoMat;InitX,InitY,Dim,Dir,Carico:Integer):Boolean;
Var StatoFunzione:Boolean;
 Begin
 StatoFunzione:=False;
 Case Dir Of {0=Nord;1=Est;2=Sud;3=Ovest}
 0:If InitX>2 Then StatoFunzione:=True;
 1:If InitY<(Dim-1) Then StatoFunzione:=True;
 2:If InitX<(Dim-1) Then StatoFunzione:=True;
 3:If InitY>2 Then StatoFunzione:=True;
 End; {Case}
 If StatoFunzione Then
 Begin
 Case Dir Of
 0:InitX:=InitX-1;
 1:InitY:=InitY+1;
 2:InitX:=InitX+1;
 3:InitY:=InitY-1;
 End; {Case}
 If (M[InitX,InitY]='O') Or ((M[InitX,InitY]='R') And (Carico>0)) Then
 StatoFunzione:=False;
 End;
 Consentita:=StatoFunzione;
 End; 
 
Procedure MuoviIntelligente(InitX,InitY:Integer;Arrivo:RecArrivi;VAR Dir:Integer);
 Begin
 If Arrivo.NuovaDestinazione Then
 Begin
 Arrivo.X:=Arrivo.NuovaX;
 Arrivo.Y:=Arrivo.NuovaY;
 End;
 Repeat
 If (Casuale MOD 2) = 1 Then
 Begin
 If InitX<Arrivo.X Then Dir:=2
 Else
 Begin
 If InitX>Arrivo.X Then Dir:=0
 Else Dir:=4;
 End;
 End
 Else
 Begin
 If InitY<Arrivo.Y Then Dir:=1
 Else
 Begin
 If InitY>Arrivo.Y Then Dir:=3
 Else Dir:=4;
 End;
 End;
 Until (Dir in [0..3]);
 End; 
 
Function Informazione(Carico:Integer;Visione:TipoVista):Char;
Var I,J:Integer;
 Ostacolo,Ricarica:Boolean;
 Begin
 Ostacolo:=False;
 Ricarica:=False;
 For I:=1 To 5 Do
 For J:=1 To 5 Do
 Begin
 If Carico>0 Then
 Begin
 Case Visione[I,J] Of
 'O':Ostacolo:=True;
 'R':Ostacolo:=True;
 End (*Case*)
 End
 Else
 Begin
 Case Visione[I,J] Of
 'O':Ostacolo:=True;
 'R':Ricarica:=True;
 End (*Case*)
 End
 End;
 If Ostacolo And Ricarica Then
 Informazione:='Z' {Ci sono sia ostacoli che ricariche}
 Else
 Begin
 If Ostacolo Then
 Informazione:='O'
 Else
 Begin
 If Ricarica Then
 Informazione:='R'
 Else
 Informazione:='N'
 End
 End
 End; 
 
Procedure Muovi(Var M:TipoMat;Var InitX,InitY:Integer;Dir:Integer;Var T,Carico:Integer);
 Begin
 Case Dir Of
 0:InitX:=InitX-1;
 1:InitY:=InitY+1;
 2:InitX:=InitX+1;
 3:InitY:=InitY-1;
 End; {Case}
 If (M[InitX,InitY]='R') And (Carico<=0) Then
 Begin
 T:=T+Ricarica;
 Carico:=TempoCarico;
 End;
 If Carico>0 Then
 Writeln('Wally potr… ricaricarsi di nuovo tra ',Carico,' passi');
 End; 
 
Procedure CalcolaDistanza(InitX,InitY:Integer;Var Arrivo:RecArrivi);
 Begin
 If Arrivo.NuovaDestinazione Then
 Arrivo.NuovaDistanza:=Abs(InitX-(Arrivo.NuovaX))+Abs(InitY-(Arrivo.NuovaY))
 Else
 Begin
 If Arrivo.Distanza<>MaxInt Then
 Arrivo.Distanza:=Abs(InitX-(Arrivo.X))+Abs(InitY-(Arrivo.Y))
 Else
 Arrivo.Distanza:=MaxInt;
 End;
 End; 
 
Function ObiettivoRaggiunto(Arrivo:RecArrivi;InitX,InitY:Integer):Boolean;
 Begin
 If Arrivo.NuovaDestinazione Then
 Begin
 ObiettivoRaggiunto:=((Arrivo.NuovaX=InitX)And(Arrivo.NuovaY=InitY))
 End
 Else
 ObiettivoRaggiunto:=False
 End; 
 
Procedure ScansaOstacolo(InitX,InitY:Integer;Var Arrivo:RecArrivi;Var Dir:Integer;Visione:TipoVista;Passi:TipoMemoria);
Var StoriaX,StoriaY,I,X,Y:Integer;
 Necessario,SfruttaMemoria:Boolean;
 Begin
 MuoviIntelligente(InitX,InitY,Arrivo,Dir);
 SfruttaMemoria:=False;
 Necessario:=False;
 X:=MaxInt;
 Y:=MaxInt;
 Case Dir Of
 0:If Visione[2,3]='O' Then Necessario:=True;
 1:If Visione[3,4]='O' Then Necessario:=True;
 2:If Visione[4,3]='O' Then Necessario:=True;
 3:If Visione[3,2]='O' Then Necessario:=True;
 End; (*case*)
 If Necessario Then
 Begin
 Case Dir Of
 0:Begin
 If (Visione[3,2]=' ') And (Visione[2,2]=' ') Then
 Begin
 X:=2;
 Y:=2;
 End
 Else
 Begin
 If (Visione[3,4]=' ') And (Visione[2,4]=' ') Then
 Begin
 X:=2;
 Y:=4;
 End
 Else
 SfruttaMemoria:=True;
 End
 End;
 1:Begin
 If (Visione[2,3]=' ') And (Visione[2,4]=' ') Then
 Begin
 X:=2;
 Y:=4;
 End
 Else
 Begin
 If (Visione[4,3]=' ') And (Visione[4,4]=' ') Then
 Begin
 X:=4;
 Y:=4;
 End
 Else
 SfruttaMemoria:=True;
 End
 End;
 2:Begin
 If (Visione[3,4]=' ') And (Visione[4,4]=' ') Then
 Begin
 X:=4;
 Y:=4;
 End
 Else
 Begin
 If (Visione[3,2]=' ') And (Visione[4,2]=' ') Then
 Begin
 X:=4;
 Y:=2;
 End
 Else
 SfruttaMemoria:=True;
 End
 End;
 3:Begin
 If (Visione[4,3]=' ') And (Visione[4,2]=' ') Then
 Begin
 X:=4;
 Y:=2;
 End
 Else
 Begin
 If (Visione[2,3]=' ') And (Visione[2,2]=' ') Then
 Begin
 X:=2;
 Y:=2;
 End
 Else
 SfruttaMemoria:=True;
 End
 End;
 End; (*case*)
 If SfruttaMemoria Then
 Begin
 For I:=1 To 5 Do
 Begin
 Storia(Passi,I,StoriaX,StoriaY);
 IF StoriaX=MaxInt Then
 Begin
 X:=StoriaX;
 Y:=StoriaY;
 End
 End
 End;
 If X<>MaxInt Then
 Begin
 Arrivo.NuovaDestinazione:=True;
 Case X Of
 1:Arrivo.NuovaX:=InitX-2;
 2:Arrivo.NuovaX:=InitX-1;
 3:Arrivo.NuovaX:=InitX;
 4:Arrivo.NuovaX:=InitX+1;
 5:Arrivo.NuovaX:=InitX+2;
 end; (*case*)
 Case Y Of
 1:Arrivo.NuovaY:=InitY-2;
 2:Arrivo.NuovaY:=InitY-1;
 3:Arrivo.NuovaY:=InitY;
 4:Arrivo.NuovaY:=InitY+1;
 5:Arrivo.NuovaY:=InitY+2;
 end; (*case*)
 end;
 End;
 MuoviIntelligente(InitX,InitY,Arrivo,Dir);
 End; 
 
Procedure MangiaRicarica(InitX,InitY:Integer;Var Arrivo:RecArrivi;Var Dir:Integer;Visione:TipoVista;Passi:TipoMemoria);
Var I,J,X,Y:Integer;
 Recuperabile,AttenzioneOstacoli:Boolean;
 Begin
 Recuperabile:=True;
 AttenzioneOstacoli:=False;
 For I:=1 To 5 Do
 For J:=1 To 5 Do
 Begin
 If Visione[I,J]='R' Then
 Begin
 X:=I;
 Y:=J;
 End;
 If (Visione[I,J]='O') Then
 AttenzioneOstacoli:=True;
 End;
 If AttenzioneOstacoli Then
 Begin
 If (Visione[2,3]='R') Then
 Begin
 X:=2;
 Y:=3;
 End
 Else
 Begin
 If (Visione[3,4]='R') Then
 Begin
 X:=3;
 Y:=4;
 End
 Else
 Begin
 If (Visione[4,3]='R') Then
 Begin
 X:=4;
 Y:=3;
 End
 Else
 Begin
 If (Visione[3,2]='R') Then
 Begin
 X:=3;
 Y:=2;
 End
 Else
 Begin
 Recuperabile:=False;
 End
 End
 End
 End
 End;
 If Recuperabile Then
 Begin
 Arrivo.NuovaDestinazione:=True;
 Case X Of
 1:Arrivo.NuovaX:=InitX-2;
 2:Arrivo.NuovaX:=InitX-1;
 3:Arrivo.NuovaX:=InitX;
 4:Arrivo.NuovaX:=InitX+1;
 5:Arrivo.NuovaX:=InitX+2;
 end; (*case*)
 Case Y Of
 1:Arrivo.NuovaY:=InitY-2;
 2:Arrivo.NuovaY:=InitY-1;
 3:Arrivo.NuovaY:=InitY;
 4:Arrivo.NuovaY:=InitY+1;
 5:Arrivo.NuovaY:=InitY+2;
 end; (*case*)
 MuoviIntelligente(InitX,InitY,Arrivo,Dir);
 End
 Else
 Begin
 ScansaOstacolo(InitX,InitY,Arrivo,Dir,Visione,Passi);
 End
 End; 
 
Procedure TrovaDir(Var M:TipoMat;T,InitX,InitY,Dim,Carico:Integer;Var Arrivo:RecArrivi;Var Dir:Integer;
 Visione:TipoVista;Passi:TipoMemoria);
Var Conto:Integer;
 Veduto:Char;
 Begin
 If Arrivo.NuovaDestinazione Then
 Begin
 Conto:=1;
 Repeat
 Conto:=Conto+1;
 If Conto>10 Then
 Begin
 Dir:=Casuale
 End
 Else
 Begin
 MuoviIntelligente(InitX,InitY,Arrivo,Dir);
 End;
 Until Consentita(M,InitX,InitY,Dim,Dir,Carico) Or (Conto>30);
 End
 Else
 Begin
 Conto:=1;
 Repeat
 Conto:=Conto+1;
 If Conto>10 Then
 Begin
 Dir:=Casuale
 End
 Else
 Begin
 If Arrivo.Distanza>T Then
 Begin
 If (Informazione(Carico,Visione)='R') Or (Informazione(Carico,Visione)='Z') Then
 MangiaRicarica(InitX,InitY,Arrivo,Dir,Visione,Passi)
 Else
 Begin
 Dir:=Casuale;
 End
 End
 Else
 Begin
 MuoviIntelligente(InitX,InitY,Arrivo,Dir);
 Veduto := Informazione(Carico,Visione);
 Case Veduto Of
 'O':ScansaOstacolo(InitX,InitY,Arrivo,Dir,Visione,Passi);
 'R':MangiaRicarica(InitX,InitY,Arrivo,Dir,Visione,Passi);
 'Z':MangiaRicarica(InitX,InitY,Arrivo,Dir,Visione,Passi);
 End; (*case*)
 End;
 End;
 Until Consentita(M,InitX,InitY,Dim,Dir,Carico) Or (Conto>30);
 End;
 {Conto indica il numero di tentativi per trovare la direzione} 
 
 If Conto>30 Then
 Begin
 Writeln('Impossibile Muoversi!!!');
 Stampa(Passi);
 Readln;
 Smemorizza(Passi);
 Halt;
 End;
 End; 
 
Procedure Vista(Var M:TipoMat;Dim,InitX,InitY:Integer;Var Visione:TipoVista);
Var I,J:Integer;
 Begin
 For I:=1 To 5 Do
 Begin
 For J:=1 To 5 Do
 Begin
 If ((InitX+(I-3)) In [2..Dim-1]) And ((InitY+(J-3)) In [2..Dim-1]) Then
 Visione[I,J]:=M[(InitX+(I-3)),(InitY+(J-3))]
 Else
 Visione[I,J]:='-';
 End;
 End;
 End; 
 
Procedure Giro(Var M:TipoMat;Var Visione:TipoVista;Var InitX,InitY:Integer;
 Dim,T:Integer;Var Arrivo:RecArrivi;Var Carico:Integer;Var Passi:TipoMemoria);
Var I,J,Dir:Integer;
 Begin
 If M[InitX,InitY]<>'D' Then
 Begin
 Vista(M,Dim,InitX,InitY,Visione);
 If M[InitX,InitY]='P' Then
 Memorizza(Passi,InitX,InitY,'P')
 Else
 Memorizza(Passi,InitX,InitY,Informazione(Carico,Visione));
 M[InitX,InitY]:=Chr(2);
 Writeln('Vita di Wally >> ',T);
 Visualizza(M,Dim);
 Readln;
 If T>0 Then
 Begin
 TrovaDir(M,T,InitX,InitY,Dim,Carico,Arrivo,Dir,Visione,Passi);
 M[InitX,InitY]:=' ';
 Muovi(M,InitX,InitY,Dir,T,Carico);
 If ObiettivoRaggiunto(Arrivo,InitX,InitY) Then
 Begin
 Arrivo.NuovaDestinazione:=False;
 Arrivo.NuovaX:=MaxInt;
 Arrivo.NuovaY:=MaxInt;
 Arrivo.NuovaDistanza:=MaxInt;
 End;
 CalcolaDistanza(InitX,InitY,Arrivo);
 If Carico>0 Then Carico:=Carico-1;
 Giro(M,Visione,InitX,InitY,Dim,T-1,Arrivo,Carico,Passi);
 End;
 End
 Else
 Begin
 Memorizza(Passi,InitX,InitY,'D');
 Writeln('Sei Arrivato Al Punto Di Uscita!!!');
 M[InitX,InitY]:=Chr(2);
 Visualizza(M,Dim);
 Readln;
 End;
 End; 
 
Procedure PreparaGiro(Var M:TipoMat;Var InitX,InitY:Integer;Dim,T:Integer;Var Arrivo:RecArrivi;Var Passi:TipoMemoria);
Var Carico:Integer;
 Visione:TipoVista;
 Begin
 M[InitX,InitY]:='P';
 Carico:=0;
 Giro(M,Visione,InitX,InitY,Dim,T,Arrivo,Carico,Passi);
 End; 
 
{Main}
Begin
End.

File: MEMORIA.PAS

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
(**************************************************************************) 
 
UNIT Memoria; 
 
(**************************************************************************) 
 
INTERFACE 
 
 CONST
 LungMemoria = 10; (*Numero elementi della memoria*) 
 
 TYPE
 TipoElementoMemoria = RECORD
 X,Y          : INTEGER;
 Informazioni : CHAR
 end;     (*record*) 
 
 Pnodo = ^TipoNodo; 
 
 TipoNodo = RECORD
 elem : TipoElementoMemoria;
 next : Pnodo
 end;     (*record*) 
 
 TipoMemoria = RECORD
 nroelem    : INTEGER;
 testa,fine : Pnodo
 end;    (*record*) 
 
(**************************************************************************) 
 
PROCEDURE AttivaMemoria(VAR Passi:TipoMemoria);
 (*OUT: attiva la memoria, adesso puoi usarla!*) 
 
PROCEDURE Memorizza(VAR Passi:TipoMemoria;InitX,InitY:INTEGER;Info:CHAR);
 (*OUT: elemento memorizzato*) 
 
PROCEDURE Smemorizza(VAR Passi:TipoMemoria);
 (*OUT: smemorizza tutta la memoria, e restituisce alla HEAP tutto
 ci• che gli spetta. Questo comando deve essere quindi eseguito
 per disattivare la memoria*) 
 
PROCEDURE Stampa(VAR Passi:TipoMemoria);
 (*OUT: stampa gli ultimi LungMemoria elementi memorizzati*) 
 
PROCEDURE Storia(Passi:TipoMemoria;N:Integer;StoriaX,StoriaY:INTEGER);
 (*OUT: ultima coordinata x registrata in StoriaX,
 da MaxInt se non esiste! Ultima coordinata y registrata
 in StoriaY, da MaxInt se non esiste*) 
 
(**************************************************************************)
IMPLEMENTATION 
 
PROCEDURE Scoda(VAR Passi:TipoMemoria);            (*OUT: scoda un elemento*)
VAR
 Temp:Pnodo; 
 
BEGIN
 Temp := Passi.Testa;
 IF Temp <> NIL THEN
 WITH Passi DO
 Begin
 Testa := Temp^.next;
 IF Testa = NIL THEN Fine := NIL;
 dispose(temp);
 NroElem := NroElem-1
 End
END; 
 
PROCEDURE AttivaMemoria(VAR Passi:TipoMemoria);         (*OUT: coda vuota*)
BEGIN
 WITH Passi DO
 Begin
 NroElem := 0;
 testa   := NIL;
 fine    := NIL
 End
END; 
 
PROCEDURE Memorizza(VAR Passi:TipoMemoria;InitX,InitY:INTEGER;Info:CHAR);   (*OUT: elemento accodato*)
VAR
 x:TipoElementoMemoria;
 Temp:Pnodo; 
 
BEGIN
 IF LungMemoria = Passi.NroElem THEN Scoda(Passi); 
 
 new(temp);
 temp^.elem.X := InitX;
 temp^.elem.Y := InitY;
 temp^.elem.Informazioni := Info;
 temp^.next := NIL; 
 
 WITH Passi DO
 Begin
 IF Testa = NIL THEN
 Testa := Temp
 ELSE
 Fine^.next := Temp;
 Fine := Temp;
 NroElem := NroElem +1
 End
END; 
 
PROCEDURE Smemorizza(VAR Passi:TipoMemoria);
VAR
 I:INTEGER;
BEGIN
 WHILE Passi.testa <> NIL DO (*se la memoria non Š vuota esegue l'iterazione*)
 BEGIN
 Scoda(Passi)
 END
END; 
 
PROCEDURE Stampa(VAR Passi:TipoMemoria);
VAR
 I:INTEGER;
 Temp:Pnodo;
BEGIN
 Temp := Passi.Testa;
 IF Passi.testa = NIL THEN
 Writeln('La memoria Š Vuota!!!')
 ELSE
 Begin
 I := 0;
 WHILE Temp <> NIL DO
 Begin
 I := I+1; 
 
 Write(I,') Coordinate X=',(Temp^.elem.X-1),' Y=',(Temp^.elem.Y-1));
 Write('  -  Info: '); 
 
 CASE Temp^.elem.Informazioni OF
 'N':Writeln('zona libera');
 'O':Writeln('ostacolo');
 'R':Writeln('ricarica');
 'P':Writeln('punto di partenza');
 'D':Writeln('punto di arrivo **');
 'Z':Writeln('ostacolo e ricarica');
 end; (*case*) 
 
 Temp := Temp^.Next
 End
 End
END; 
 
PROCEDURE Storia(Passi:TipoMemoria;N:Integer;StoriaX,StoriaY:INTEGER);
VAR
 Puntatore:Pnodo;
 I:INTEGER;
BEGIN
 Puntatore:=Passi.Testa;
 FOR I:=1 TO (Passi.NroElem-N) DO
 Puntatore := Puntatore^.Next; 
 
 IF Puntatore<>NIL THEN
 Begin
 StoriaX := Puntatore^.elem.X;
 StoriaY := Puntatore^.elem.Y
 End
 ELSE
 Begin
 StoriaX := MaxInt;
 StoriaY := MaxInt
 End
END; 
 
BEGIN                                                   (*MAIN UNIT*)
END.                                                    (*MAIN UNIT*)

I commenti sono chiusi.