In collaborazione con:
[IoProgrammo]
Il BUG di scansione

Ultimo aggiornamento: 18-nov-1999

Questa pagina è semplicemente una collezione delle esperienze fatte da alcuni croboticisti alle prese con il bug dell' angolo 0.
Iniziamo con Daniele Nuzzo:

Ho fatto qualche prova per vedere quanto possa influire il bug sui risultati.

Con questi due semplicissimi crobots...

/* Fix.r: fa da bersaglio */

main()
{
  while (loc_x()<850) drive(0,45);
  drive (0,0);
  while (loc_y()>100) drive(270,45);
  drive (270,0);
  while (loc_y()<100) drive(90,10);
  drive (90,0);
  while(speed()) ;
  while (1) if (loc_y()==100) cannon(90,400);
}
 

/* Fix2.r: verifica il bug */
int t,rng;

main()
{
  while (loc_x()>500) drive(180,45);
  drive (180,0);
  while (loc_x()<500) drive(0,45);
  drive (0,0);
  while (loc_y()>100) drive(270,45);
  drive (270,0);
  while (loc_y()<100) drive(90,10);
  drive (90,0);
  t=500;
  while(speed()) ;
  while (--t) if (loc_y()==100) cannon(90,400);
  while (1) if (rng=scan(0,10)) cannon(0,rng);

}

... si puo' verificare con assoluta certezza se c'e' il bug: infatti si
posizionano sulla stessa ordinata (y=100) a distanza di circa 500 e, dopo
aver verificato, sparando in aria mentre sono fermi, che il valore di y sia
corretto per entrambi Fix2.r fa fuori Fix.r (ma solo se lo vede!!!).
Modificando leggermente i due crobots si possono effettuare diverse prove
per vedere quali sono gli angoli in cui c'e' il bug (se ne fate qualcuno
date i risultati, cosi' cerchiamo di capirci qualcosa in piu').

Io ho modificato fix2 in questo modo:

int t,rng;

main()
{
  while (loc_x()>500) drive(180,45);
  drive (180,0);
  while (loc_x()<500) drive(0,45);
  drive (0,0);
  while (loc_y()>100) drive(270,45);
  drive (270,0);
  while (loc_y()<100) drive(90,10);
  drive (90,0);
  t=500;
  while(speed()) ;
  while (--t) if (loc_y()==100) cannon(90,400);
  while (1) {
    if (rng=scan(349,10)) cannon(0,rng);
    if (rng=scan(371,10)) cannon(0,rng);
    if (rng=scan(360,0)) cannon(0,rng);
    if (rng=scan(0,0)) cannon(0,rng);
    if (rng=scan(0,3)) cannon(0,rng);
    if (rng=scan(360,3)) cannon(0,rng);
    if (rng=scan(0,10)) cannon(0,rng);
    if (rng=scan(5,5)) cannon(0,rng);
    if (rng=scan(-5,5)) cannon(0,rng);
    if (rng=scan(-1,0)) cannon(0,rng);
    if (rng=scan(1,0)) cannon(0,rng);
    if (rng=scan(-2,0)) cannon(0,rng);
    if (rng=scan(2,0)) cannon(0,rng);
    if (rng=scan(-3,0)) cannon(0,rng);
    if (rng=scan(3,0)) cannon(0,rng);
    if (rng=scan(361,0)) cannon(0,rng);
    if (rng=scan(362,0)) cannon(0,rng);
    if (rng=scan(363,0)) cannon(0,rng);
    if (rng=scan(359,0)) cannon(0,rng);
    if (rng=scan(358,0)) cannon(0,rng);
    if (rng=scan(357,0)) cannon(0,rng);
    if (rng=scan(0,1)) cannon(0,rng);
    if (rng=scan(1,1)) cannon(0,rng);
    if (rng=scan(2,1)) cannon(0,rng);
    if (rng=scan(-1,1)) cannon(0,rng);
    if (rng=scan(-2,1)) cannon(0,rng);
  }
}

... e facendo combattere 2000 incontri con limite 40000 (piu' che
sufficiente) ho ottenuto i seguenti risultati:

Nome del Robot     Partite   Partite   Partite   Partite   Punteggio Perc
Combattente        Giocate   vinte     Nulle     Perse     Ottenuto    %

 1       fix2       2000      1390      610       0         4780      79.6
 2        fix       2000      0         610       1390      610       10.1

Scheda tecnica del Crobot fix2

Partite combattute  2000               Punteggio finale    4780
Partite vinte       1390               Efficienza          79.6
Partite pareggiate  610
Partite perse       0
 

                          Le vittorie sono maturate cosi'
CPU * 10000      |<2  |<4  |<6  |<8  |<10 |<12 |<14 |<16 |<18 |<20 |Pari
                 |    |    |    |    |    |    |    |    |    |    |
 0 <Danni< 20    |1387|3   |0   |0   |0   |0   |0   |0   |0   |0   |610
 20 <Danni< 40   |0   |0   |0   |0   |0   |0   |0   |0   |0   |0   |0
 40 <Danni< 60   |0   |0   |0   |0   |0   |0   |0   |0   |0   |0   |0
 60 <Danni< 80   |0   |0   |0   |0   |0   |0   |0   |0   |0   |0   |0
 80 <Danni< 100  |0   |0   |0   |0   |0   |0   |0   |0   |0   |0   |0

fix2 ha riportato i seguenti risultati

Nome del Robot     Partite   Partite   Perc.     Partite   Percentuale
Combattente        giocate   vinte     vitt.     patte     aggiustata

 1       fix        2000      1390      69.5      610       79.6

Considerazioni:
1) in almeno il 30% dei casi il bersaglio sparisce e non c'e' modo di
trovarlo!!!
2) sembra che il bug ci sia nell'intervallo da -10 a zero.

Ma Maurizio Camangi non sembra essere daccordo:

Ragazzi! Spero di aver ragione!
Ho ripreso in mano i due robottini di prova di Daniele, fix.r e fix2.r (vi
ricordate i risultati ottenuti?).
Ho modificato fix2.r usando tutti angoli positivi, sommando 360 ove necessario, ed ecco il listato:
(commentato il codice originale di Daniele)

/* Fix2.r: verifica il bug */
int t,rng;

main()
{
  while (loc_x()>500) drive(180,45);
  drive (180,0);
  while (loc_x()<500) drive(0,45);
  drive (0,0);
  while (loc_y()>100) drive(270,45);
  drive (270,0);
  while (loc_y()<100) drive(90,10);
  drive (90,0);
  t=500;
  while(speed()) ;
  while (--t) if (loc_y()==100) cannon(90,400);
  while (1) {
/* codice originale
    if (rng=scan(349,10)) cannon(0,rng);
    if (rng=scan(371,10)) cannon(0,rng);
    if (rng=scan(360,0)) cannon(0,rng);
    if (rng=scan(0,0)) cannon(0,rng);
    if (rng=scan(0,3)) cannon(0,rng);
    if (rng=scan(360,3)) cannon(0,rng);
    if (rng=scan(0,10)) cannon(0,rng);
    if (rng=scan(5,5)) cannon(0,rng);
    if (rng=scan(-5,5)) cannon(0,rng);
    if (rng=scan(-1,0)) cannon(0,rng);
    if (rng=scan(1,0)) cannon(0,rng);
    if (rng=scan(-2,0)) cannon(0,rng);
    if (rng=scan(2,0)) cannon(0,rng);
    if (rng=scan(-3,0)) cannon(0,rng);
    if (rng=scan(3,0)) cannon(0,rng);
    if (rng=scan(361,0)) cannon(0,rng);
    if (rng=scan(362,0)) cannon(0,rng);
    if (rng=scan(363,0)) cannon(0,rng);
    if (rng=scan(359,0)) cannon(0,rng);
    if (rng=scan(358,0)) cannon(0,rng);
    if (rng=scan(357,0)) cannon(0,rng);
    if (rng=scan(0,1)) cannon(0,rng);
    if (rng=scan(1,1)) cannon(0,rng);
    if (rng=scan(2,1)) cannon(0,rng);
    if (rng=scan(-1,1)) cannon(0,rng);
    if (rng=scan(-2,1)) cannon(0,rng);
*/
    if (rng=scan(349,10)) cannon(360,rng);
    if (rng=scan(371,10)) cannon(360,rng);
    if (rng=scan(360,0)) cannon(360,rng);
    if (rng=scan(360,0)) cannon(360,rng);
    if (rng=scan(360,3)) cannon(360,rng);
    if (rng=scan(360,3)) cannon(360,rng);
    if (rng=scan(360,10)) cannon(360,rng);
    if (rng=scan(365,5)) cannon(360,rng);
    if (rng=scan(355,5)) cannon(360,rng);
    if (rng=scan(359,0)) cannon(360,rng);
    if (rng=scan(361,0)) cannon(360,rng);
    if (rng=scan(358,0)) cannon(360,rng);
    if (rng=scan(362,0)) cannon(360,rng);
    if (rng=scan(357,0)) cannon(360,rng);
    if (rng=scan(363,0)) cannon(360,rng);
    if (rng=scan(361,0)) cannon(360,rng);
    if (rng=scan(362,0)) cannon(360,rng);
    if (rng=scan(363,0)) cannon(360,rng);
    if (rng=scan(359,0)) cannon(360,rng);
    if (rng=scan(358,0)) cannon(360,rng);
    if (rng=scan(357,0)) cannon(360,rng);
    if (rng=scan(360,1)) cannon(360,rng);
    if (rng=scan(361,1)) cannon(360,rng);
    if (rng=scan(362,1)) cannon(360,rng);
    if (rng=scan(359,1)) cannon(360,rng);
    if (rng=scan(358,1)) cannon(360,rng);
  }
}

Ed ecco i risultati:

    Nome  robot  - Partite - Partite - Partite - Partite - Punteggio - Perc
    Combattente    giocate    vinte     patte     perse    ottenuto      %

 1         fix2      2000     2000         0         0        6000    100.00
 2          fix      2000        0         0      2000           0      0.00
 
 

Scheda tecnica del crobot fix2:

In classifica e' alla posizione numero 1

Partite combattute:2000  Punteggio finale: 6000
Partite vinte     :2000  Efficienza      :100.00
Partite pareggiate:   0
Partite perse     :   0
 

                         Le vittorie sono maturate cosi'           |Pareggi|
CPU * 10000  |< 2 |< 4 |< 6 |< 8 |<10 |<12 |<14 |<16 |<18 |<20 |1Sup|2Sup|3Sup
             |    |    |    |    |    |    |    |    |    |    |    |    |
 0<Danni< 20 |1998|   2|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0
20<Danni< 40 |   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0
40<Danni< 60 |   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0
60<Danni< 80 |   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0
80<Danni<100 |   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0|   0

 fix2 ha riportato i seguenti risultati

 Nome del Robot    Partite   Partite   Perc.     Partite   Percentuale
  Combattente      giocate    vinte    vitt.      patte    aggiustata
 1          fix     2000      2000    100.00        0       100.00

Che cosa vi avevo detto io???!!!???
Crobots effettua l'operazione di modulo per angoli negativi; nel codice di
Daniele alcuni scan(), usano numeri negativi o nulli (o cmq valori per cui il range +/- 10 gradi finisce nei negativi); sostituendo a tali valori quelli che si ottengono sommando 360 funziona tutto.
Ditemi che non ho bevuto :-)

Purtroppo per noi però ha ragione Daniele:

No, Maurizio; purtroppo il bug c'e'!!! Anche se sotto Linux la situazione è migliore!!!
Ho provato lo stesso codice sotto Linux ed in effetti i risultati sono gli
stessi dei tuoi, ma nel while ci sono numerosi scan in cascata, che combinati annullano l'effetto del bug. Anche se in realta' bastano 2 scan
per verificare la presenza dei robot in direzione zero (circa); con uno
solamente non funziona, mentre dovrebbe!!! Se provi inserendo scan(360,10)
da solo non basta ad eliminare il bug, che quindi c'e' sicuramente. Si puo' invece risolvere il problema con 2 scan tipo scan(355,5)+scan(365,5) oppure scan(350,10)+scan(370,10).
Dopo aver fatto ulteriori prove, penso che in questo caso (con Linux) il bug abbia questo effetto: divide in due parti l'angolo di scansione in
corrispondenza dello zero (o multipli modulo 360); quindi se la scansione
parte da un angolo che si trova sopra lo zero individuera' tutti i crobots
sopra, ma non quelli sotto lo zero; viceversa, se l'angolo iniziale di
scansione e' inferiore a zero. Lo zero dovrebbe essere incluso nella
scansione positiva, ma non in quella negativa e cio' introduce un ulteriore problema: e' piu' probabile che un robot in movimento riesca a "passare"
indenne anche ai 2 scan combinati (ecco spiegato perche' in genere si
controlla l'arena con incrementi di 20 gradi e non di 21).
Concludendo credo che comunque la situazione sia molto piu' gestibile almeno per il controllo dell'arena prima degli spostamenti. Rimane il problema per le routine di fuoco che con ulteriori controlli rischiano di diventare troppo lente.