Blame |
Last modification |
View Log
| RSS feed
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
/**
------------
CVS : $Id: lupo.c,v 1.1 2004-08-05 11:34:36 pj Exp $
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2004-08-05 11:34:36 $
------------
**/
/*
* Copyright (C) 2000 Paolo Gai and Giorgio Buttazzo
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*--------------------------------------------------------------*/
/* SIMULATION OF RANDOM FLIES */
/*--------------------------------------------------------------*/
#include <kernel/kern.h>
#include <drivers/glib.h>
#include <drivers/keyb.h>
#include <drivers/mouse.h>
#include <semaphore.h>
#include <stdlib.h>
#include <math.h>
#define YMENU 10 /* menu level */
#define XMIN 50
#define XMAX 600
#define YMIN 100
#define YMAX 450
#define VEL 5 /* Velocità della pecora (def. = 5)*/
#define VELWOLF 4 /* Velocità del lupo(def. = 4) */
#define ANG 30 /* angolo massimo sterzata (30) */
#define D 3 /* raggio pecore e lupi */
#define ESC 27 /* ASCII code of ESCAPE key */
#define MAXPECORE 4 /* Massimo numero di pecore */
#define MAXLUPI 3 /* Massimo numero di lupi */
#define WOLFGROUP 1
#define SHEEPGROUP 1
#define HUNTGROUP 1
/* Variabili globali utilizzate nel programma*/
double tick
= 1.0; /* system tick = 1 ms */
int hunt_period
= 40000; /* Periodo del task cacciatore */
int sheep_period
= 40000; /* Periodo del task lupo */
int wolf_period
= 40000; /* Periodo del task pecora */
int hunt_wcet
= 100; /* wcet del task cacciatore */
int sheep_wcet
= 100; /* wcet del task pecora */
int wolf_wcet
= 100; /* wcet del task lupo */
int num_p
= 0; /* numero iniziale di pecore */
int num_l
= 0; /* numero iniziale di lupi */
int num_c
= 0; /* numero iniziale di cacciatori */
PID pidp
,pidl
,pidc
; /* etichetta creata dal S.O. attribuita ad ogni task*/
sem_t mutex
; /* semaforo di mutua */
/*--------------------------------------------------------------*/
/*Definizione della struttura posizione*/
struct pos
{
int x
, y
; /*Posizione nel piano di ogni singolo task*/
sem_t priv
; /*Semaforo relativo alla posizione di ogni singolo task*/
int death
; /*Flag di vita o di morte di ogni singolo task*/
};
/*--------------------------------------------------------------*/
/*Generazione di vettori di struttura posizione per ogni task*/
struct pos pecora
[MAXPECORE
];
struct pos lupo
[MAXLUPI
];
struct pos caccia
[1];
/*--------------------------------------------------------------*/
/*Funzione per disegnare a video lupi e pecore*/
void draw_obj
(int x
, int y
, int c
)
{
sem_wait
(&mutex
); /*Semaforo di mutua per proteggere la scrittura a video*/
grx_disc
(x
, y
, D
, c
);
sem_post
(&mutex
);
}
/*--------------------------------------------------------------*/
/*Funzione di inizializzazione per tutti le variabili di ogni task*/
void init_sem
()
{
int i
;
sem_init
(&mutex
,0,1);
/*Inizializzazione del vettore di struttura posizione pecora*/
for (i
=0;i
<MAXPECORE
;i
++){
sem_init
(&pecora
[i
].
priv,0,1);
pecora
[i
].
x = 0;
pecora
[i
].
y = 0;
pecora
[i
].
death = 0;
}
/*Inizializzazione del vettore di struttura posizione lupi*/
for (i
=0;i
<MAXLUPI
;i
++){
sem_init
(&lupo
[i
].
priv,0,1);
lupo
[i
].
x = 0;
lupo
[i
].
y = 0;
lupo
[i
].
death = 0;
}
/*Inizializzazione del vettore di struttura posizione cacciatore*/
sem_init
(&caccia
[0].
priv,0,1);
caccia
[0].
x = 0;
caccia
[0].
y = 0;
caccia
[0].
death = 0;
}
/******************************************************************/
/*Task pecora*/
TASK sheep
(void *arg
)
{
int x
, y
; /*Posizione futura*/
int ox
, oy
; /*Posizione attuale*/
int dx
, dy
, da
; /*Spostamento lungo x e y e angolare*/
int teta
, col
; /*Angolo di direzione dello spostamento e colore pecora*/
int outx
, outy
,i_libera
,i
; /*Limiti perimetrali*/
double r
; /*Angolo di direzione dello spostamento in radianti*/
i_libera
= 0; /*Inizializzazione della prima posizione libera nel vettore di struttura pecora*/
for(i
=0;i
<MAXPECORE
;i
++){ /*Ciclo per cercare la prima posizione libera*/
sem_wait
(&pecora
[i
].
priv); /*Proteggiamo la lettura di ogni singola posizione del vettore */
if (!pecora
[i
].
x) i_libera
= i
; /*Le posizioni libere si contraddistinguono per x=0 e y=0*/
sem_post
(&pecora
[i
].
priv);
}
num_p
++; /*Incremento del numero di pecore*/
i
= i_libera
; /*La posizione nel vettore attribuita al task è la prima libera trovata*/
sem_wait
(&pecora
[i
].
priv); /*Proteggiamo l'attribuzione della posizione di origine della pecora*/
pecora
[i
].
x = ox
= x
= XMAX
- 20;
pecora
[i
].
y = oy
= y
= YMAX
- 20;
//pecora[i].pid = pidp;
sem_post
(&pecora
[i
].
priv);
teta
= 0; /*Inizializzazione dell' angolo di direzione dello spostamento*/
col
= 29; /* colore della pecora*/
while (1) { /*Ciclo infinito del task*/
/*Calcolo casuale della posizione della pecora*/
da
= rand()%(2*ANG
) - ANG
; /* da = [-ANG,ANG] */
teta
+= da
;
if (teta
> 360) teta
-= 360;
if (teta
< 0) teta
+= 360;
r
= (double)teta
* PI
/ 180.
;
dx
= (float)(VEL
* cos(r
));
dy
= (float)(VEL
* sin(r
));
x
+= dx
;
y
+= dy
;
outx
= (x
>= XMAX
) || (x
<= XMIN
); /*Controllo posizione all'interno del perimetro*/
outy
= (y
>= YMAX
) || (y
<= YMIN
);
if (outx
|| outy
) { /*In caso di uscita dal perimetro voluto ricalcolo dx e dy
in modo che la pecora non esca da esso*/
x
= x
- dx
;
y
= y
- dy
;
if (outx
) teta
= 180 - teta
;
if (outy
) teta
= -teta
;
if (teta
> 360) teta
-= 360;
if (teta
< 0) teta
+= 360;
r
= (double)teta
* PI
/ 180.
;
dx
= (float)(VEL
* cos(r
));
dy
= (float)(VEL
* sin(r
));
x
+= dx
;
y
+= dy
;
}
sem_wait
(&pecora
[i
].
priv);
if (pecora
[i
].
death == 1) { /*Controllo sul flag di vita o di morte del task pecora.*/
pecora
[i
].
x = 0; /* Se il flag è uguale a 1 la pecora "deve morire". */
pecora
[i
].
y = 0; /*Questo lo indichiamo mettendo le sue posizioni in 0*/
pecora
[i
].
death = 0; /*Rimettiamo il flag di vita o morte a 0*/
num_p
--; /*Decremento del numero di pecore*/
draw_obj
(ox
, oy
, 0); /*Chiamata della funzione per disegnare a video una pecora nera=morta*/
sem_post
(&pecora
[i
].
priv);
return 0;
}
pecora
[i
].
x = x
; /*Attribuzione delle nuove posizioni*/
pecora
[i
].
y = y
;
sem_post
(&pecora
[i
].
priv);
draw_obj
(ox
, oy
, 0); /*Disegno della nuova posizione cancellando precedentemante quella vecchia*/
draw_obj
(x
, y
, col
);
ox
= x
; oy
= y
; /*Nuove posizioni attuali*/
task_endcycle
();
}
}
/****************************************************************/
/*Task lupo*/
TASK wolf
(void *arg
)
{
int x
, y
; /*Posizione futura*/
int ox
, oy
; /*Posizione attuale*/
int dx
, dy
; /*Spostamento lungo x e y*/
int deltax
,deltay
; /*Distanza lupo pecora lungo l'asse x e lungo l'asse y*/
int ipo
,ipo_min
; /*Ipotenusa e ipotenusa minima di distanza tra lupo e pecora*/
int i_min
,i
,j_libera
,j
; /*indici della pecora più vicina, della prima posizione libera sul vettore*/
int teta
, col
; /*Angolo di direzione dello spostamento e colore lupo*/
int outx
, outy
; /*Limiti perimetrali*/
double r
=0; /*Angolo di direzione dello spostamento in radianti*/
j_libera
= 0; /*Inizializzazione della prima posizione libera nel vettore di struttura lupo*/
for(j
=0;j
<MAXLUPI
;j
++){ /*Ciclo per cercare la prima posizione libera*/
sem_wait
(&lupo
[j
].
priv); /*Proteggiamo la lettura di ogni singola posizione del vettore */
if (!lupo
[j
].
x) j_libera
= j
; /*Le posizioni libere si contraddistinguono per x=0 e y=0*/
sem_post
(&lupo
[j
].
priv);
}
num_l
++; /*Incremento del numero di lupi*/
j
= j_libera
; /*La posizione nel vettore attribuita al task è la prima libera trovata*/
sem_wait
(&lupo
[j
].
priv); /*Proteggiamo l'attribuzione della posizione di origine del lupo */
lupo
[j
].
x = ox
= x
= XMIN
+ 20;
lupo
[j
].
y = oy
= y
= YMIN
+ 20;
sem_post
(&lupo
[j
].
priv);
teta
= 0; /*Inizializzazione dell' angolo di direzione dello spostamento*/
col
= 4; /* colore lupo*/
while (1) { /*Ciclo infinito del task*/
/*controllo posizione cacciatore*/
sem_wait
(&caccia
[0].
priv);
deltax
= caccia
[0].
x-ox
; /*Calcolo della distanza tra lupo e cacciatore*/
deltay
= caccia
[0].
y-oy
;
sem_post
(&caccia
[0].
priv);
if (abs(deltax
)<30 && abs(deltay
)<30){ /*Se la distanza è minore di 30 pixel il lupo deve scappare dal cacciatore*/
if (deltax
==0){ /*calcolo degli angoli di spostamento per fuggire dal cacciatore*/
if (deltay
>0) teta
=-45;
if (deltay
<0) teta
=45;
}
else{
teta
=(180/PI
)*atan(deltay
/deltax
);
if (deltax
<0) teta
=45+teta
;
if (deltax
>0) teta
=-(teta
+90);
}
}else
{
/*controllo pecora piu vicina*/
ipo_min
=6000; /*ipotenusa in modo da averne sempre una minore*/
i_min
=0; /*Inizializzazione dell' indice della pecora più vicina*/
for(i
=0;i
<MAXPECORE
;i
++){ /*Per ogni pecora controllo la distanza lupo-pecora*/
sem_wait
(&pecora
[i
].
priv);
if (pecora
[i
].
x){ /*la posizione della pecora è 0 quando è morta*/
deltax
=pecora
[i
].
x-ox
; /*calcolo distanza lupo-pecora lungo x*/
deltay
=pecora
[i
].
y-oy
; /*calcolo distanza lupo-pecora lungo y*/
sem_post
(&pecora
[i
].
priv);
ipo
=sqrt(deltax
*deltax
+deltay
*deltay
); /*Calcolo dell'ipotenusa=distanza tra lupo e pecora*/
if (ipo
<ipo_min
) {ipo_min
=ipo
;i_min
=i
;} /*Calcolo l'ipotenusa più piccola*/
}else
sem_post
(&pecora
[i
].
priv);
}
/*calcolo la distanza della pecora piu vicina*/
sem_wait
(&pecora
[i_min
].
priv);
deltax
=pecora
[i_min
].
x-ox
;
deltay
=pecora
[i_min
].
y-oy
;
if (deltax
==0){ /*Calcolo angoli per far inseguire al lupo la pecora più vicina*/
if (deltay
>0) teta
=90;
if (deltay
<0) teta
=-90;
}
else{
teta
=(180/PI
)*atan(deltay
/deltax
);
if (deltax
<0) teta
=180+teta
;
}
//controllo se posso uccidere la pecora
if ((abs(deltax
)<2)&&(abs(deltay
)<2)) pecora
[i_min
].
death = 1; /*Se il lupo è sopra la pecora,questa deve morire*/
sem_post
(&pecora
[i_min
].
priv);
}
r
= (double)teta
* PI
/ 180.
; /*Calcolo l'angolo in radianti*/
dx
= (float)((VELWOLF
+j
) * cos(r
)); /*Una volta calcolato l'angolo di spostamento,*/
dy
= (float)((VELWOLF
+j
) * sin(r
)); /*calcolo i relativi spostamenti lungo x e y*/
x
+= dx
; /*calcolo le nuove posizioni*/
y
+= dy
;
outx
= (x
>= XMAX
) || (x
<= XMIN
); /*Controllo posizione all'interno del perimetro*/
outy
= (y
>= YMAX
) || (y
<= YMIN
);
if (outx
|| outy
) { /*In caso di uscita dal perimetro voluto ricalcolo dx e dy
in modo che il lupo non esca da esso*/
x
= x
- dx
;
y
= y
- dy
;
if (outx
) teta
= 180 - teta
;
if (outy
) teta
= -teta
;
if (teta
> 360) teta
-= 360;
if (teta
< 0) teta
+= 360;
r
= (double)teta
* PI
/ 180.
;
dx
= (float)(VEL
* cos(r
));
dy
= (float)(VEL
* sin(r
));
x
+= dx
;
y
+= dy
;
}
sem_wait
(&lupo
[j
].
priv);
if (lupo
[j
].
death == 1) { /*Controllo sul flag di vita o di morte del task lupo*/
lupo
[j
].
x = 0; /* Se il flag è uguale a 1 il lupo "deve morire". */
lupo
[j
].
y = 0; /*Questo lo indichiamo mettendo le sue posizioni in 0*/
lupo
[j
].
death = 0; /*Rimettiamo il flag di vita o morte a 0*/
num_l
--; /*Decremento del numero di lupi*/
draw_obj
(ox
, oy
, 0); /*Chiamata della funzione per disegnare a video un lupo nero=morto*/
sem_post
(&lupo
[j
].
priv);
return 0;
}
lupo
[j
].
x = x
; /*Attribuzione delle nuove posizioni*/
lupo
[j
].
y = y
;
sem_post
(&lupo
[j
].
priv);
draw_obj
(ox
, oy
, 0); /*Disegno della nuova posizione cancellando precedentemante quella vecchia*/
draw_obj
(x
, y
, col
);
ox
= x
; oy
= y
; /*Nuove posizioni attuali*/
task_endcycle
();
}
}
/****************************************************************/
void my_mouse_handler
(MOUSE_EVT
*m
)
{
grx_box
(caccia
[0].
x-3,caccia
[0].
y-3,caccia
[0].
x+3,caccia
[0].
y+3,0); /*Cancella la posizione precedente del cacciatore disegnando un rettangolo nero*/
grx_box
(m
->x
-3,m
->y
-3,m
->x
+3,m
->y
+3,2); /*disegno del cursore a forma di rettangolino attorno alla posizione attuale*/
sem_wait
(&caccia
[0].
priv);
caccia
[0].
x = m
->x
; /*Attribuisco al cacciatore le nuove coordinate del mouse*/
caccia
[0].
y = m
->y
;
sem_post
(&caccia
[0].
priv);
}
/****************************************************************/
TASK cacciatore
(void *arg
)
{
int i
= 0;
int deltax
,deltay
; /*Distanza cacciatore-lupo lungo l'asse x e lungo l'asse y*/
num_c
++; /*incremento del numero di cacciatori*/
mouse_on
(); /*attivazione e visualizzazione del mouse*/
mouse_hook
(my_mouse_handler
); /*chiamata all'hook*/
while(1){ /*controllo infinito per vedere se il lupo è da ammazzare*/
if (i
== MAXLUPI
) i
= 0; /*Se ha controllato tutti i lupi ricomincia dal primo nel vettore*/
sem_wait
(&lupo
[i
].
priv);
if (lupo
[i
].
x){ /*la posizione del lupo è 0 solo quando è morto*/
deltax
=lupo
[i
].
x-caccia
[0].
x; /*calcolo la distanza tra lupo e cacciatore*/
deltay
=lupo
[i
].
y-caccia
[0].
y;
if (abs(deltax
)<4 && abs(deltay
)<4) lupo
[i
].
death=1; /*Se il cacciatore è vicino al lupo questo deve morire*/
}
sem_post
(&lupo
[i
].
priv);
i
++; /*Incrementa i per controllare il lupo successivo*/
task_endcycle
();
}
return 0;
}
/****************************************************************/
/* This function is called when the system exits */
void byebye
(void *arg
)
{
mouse_end
();
grx_close
();
cprintf
("Bye Bye!\n");
}
/****************************** MAIN ******************************/
int main
(int argc
, char **argv
)
{
HARD_TASK_MODEL m
;
char c
; /* caratere dalla tastiera */
int i
= 0; /* numero di tasks creati */
TIME seme
; /* used to init the random seed */
// Inizializzazione del mouse
MOUSE_PARMS mouse
= BASE_MOUSE
;
mouse_def_ps2
(mouse
);
mouse_init
(&mouse
);
mouse_limit
(XMIN
,YMIN
,XMAX
,YMAX
); /* limiti del mouse all'interno del rettangolo di gioco*/
mouse_position
(XMIN
+20,YMAX
-20); /* posizione di partenza cacciatore*/
mouse_threshold
(10); /* sensibilità del mouse */
// Inizializzazione dei vettori di strutture
init_sem
();
/* Set the closing function */
sys_atrunlevel
(byebye
, NULL
, RUNLEVEL_BEFORE_EXIT
);
/* graphic card Initialization */
if (grx_init
() < 1) {
sys_abort
(1);
}
if (grx_open
(640, 480, 8) < 0) {
cprintf
("GRX Err\n");
sys_abort
(1);
}
/* The scenario */
grx_rect
(XMIN
-D
-1, YMIN
-D
-1, XMAX
+D
+1, YMAX
+D
+1, 14);
grx_text
("Simulazione di caccia al Lupo", XMIN
, YMENU
+10, 13, 0);
grx_text
("p crea una pecora" , XMIN
, YMENU
+20, 12, 0);
grx_text
("l crea un lupo" , XMIN
, YMENU
+30, 12, 0);
grx_text
("c crea un cacciatore " , XMIN
, YMENU
+40, 12, 0);
grx_text
("ESC exit to DOS" , XMIN
, YMENU
+50, 12, 0);
/* The program waits a space to create a fly */
c
= keyb_getch
(BLOCK
);
/* randomize!!!! */
seme
= sys_gettime
(NULL
);
srand(seme
);
do {
if ((c
== 'p')&&(num_p
<MAXPECORE
)) { /*se il numero di pecore max è raggiunto non crearne altre*/
hard_task_default_model
(m
);
hard_task_def_ctrl_jet
(m
);
hard_task_def_arg
(m
, (void *)i
);
hard_task_def_wcet
(m
, sheep_wcet
);
hard_task_def_mit
(m
, sheep_period
);
hard_task_def_group
(m
, SHEEPGROUP
);
hard_task_def_usemath
(m
);
pidp
= task_create
("sheep", sheep
, &m
, NULL
);
if (pidp
== NIL
) {
grx_close
();
perror("Could not create task <sheep>");
sys_abort
(1);
}
task_activate
(pidp
);
}
if ((c
== 'l')&&(num_l
<MAXLUPI
)) { /*se il numero di lupi max è raggiunto non crearne altri*/
hard_task_default_model
(m
);
hard_task_def_ctrl_jet
(m
);
hard_task_def_arg
(m
, (void *)i
);
hard_task_def_wcet
(m
, wolf_wcet
);
hard_task_def_mit
(m
, wolf_period
);
hard_task_def_group
(m
, WOLFGROUP
);
hard_task_def_usemath
(m
);
pidl
= task_create
("wolf", wolf
, &m
, NULL
);
if (pidl
== NIL
) {
grx_close
();
perror("Could not create task <wolf>");
sys_abort
(1);
}
task_activate
(pidl
);
}
if ((c
== 'c') && (num_c
== 0)) { /*se il caccaiatore è già stato creato non crearne altri*/
hard_task_default_model
(m
);
hard_task_def_ctrl_jet
(m
);
hard_task_def_arg
(m
, (void *)i
);
hard_task_def_wcet
(m
, hunt_wcet
);
hard_task_def_mit
(m
, hunt_period
);
hard_task_def_group
(m
, HUNTGROUP
);
hard_task_def_usemath
(m
);
pidc
= task_create
("cacciatore", cacciatore
, &m
, NULL
);
if (pidc
== NIL
) {
grx_close
();
perror("Could not create task <cacciatore>");
sys_abort
(1);
}
task_activate
(pidc
);
}
c
= keyb_getch
(BLOCK
);
} while (c
!= ESC
);
sys_end
();
return 0;
}
/*--------------------------------------------------------------*/