Initial commit
This commit is contained in:
@@ -0,0 +1,722 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
#define CACHE_SIZE 1024
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// BEGIN INIZIALIZZAZIONE DELLA MAPPA
|
||||
|
||||
|
||||
// BEGIN STRUTTURE
|
||||
// Struttura per rappresentare una rotta aerea
|
||||
typedef struct {
|
||||
int dest_x, dest_y; // Coordinate destinazione
|
||||
int cost; // Costo della rotta
|
||||
} AirRoute;
|
||||
|
||||
|
||||
// Struttura per rappresentare un esagono
|
||||
typedef struct {
|
||||
int land_cost; // Costo di uscita via terra (0 = bloccato)
|
||||
AirRoute air_routes[5]; // Rotte aeree uscenti
|
||||
int air_route_count; // Numero di rotte aeree
|
||||
} Hexagon;
|
||||
|
||||
|
||||
// Struttura per la mappa
|
||||
typedef struct {
|
||||
int rows, cols; // Dimensioni della matrice
|
||||
Hexagon** grid; // Matrice
|
||||
} HexMap;
|
||||
|
||||
|
||||
// Struttura per la coda in change_cost
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int dist;
|
||||
} QueueNode;
|
||||
|
||||
|
||||
// END
|
||||
|
||||
|
||||
void init_map(HexMap* map, int cols, int rows){
|
||||
// FUNZIONAMENTO:
|
||||
// Gli passo una struttura HexMap e gli inserisco il numero di colonne e righe.
|
||||
// La matrice è formata da un "array" di puntatori alle teste delle colonne. Per farlo alloco dinamicamente lo spazio per contenere tutti
|
||||
// i puntatori agli inizi delle colonne.
|
||||
// Vado poi a scorrere ogni elemento della matrice ed a inizializarli con i valori land_cost=1 e air_route_count=0.
|
||||
|
||||
map -> rows = rows; // Inserisce le dimensioni negli attributi dell'oggetto'
|
||||
map -> cols = cols;
|
||||
|
||||
// Genero la matrice di esagoni
|
||||
map -> grid = (Hexagon**) malloc(cols * sizeof(Hexagon*)); // Alloco lo spazio del primo livello della matrice
|
||||
|
||||
for (int i=0; i<map -> cols; i++){
|
||||
map -> grid[i] = (Hexagon*) malloc(rows * sizeof(Hexagon)); // Alloco lo spazio del secondo livello della matrice
|
||||
|
||||
for (int j=0; j<map -> rows; j++){
|
||||
map -> grid[i][j].land_cost=1; // Inizializzo i valori degli esagoni
|
||||
map->grid[i][j].air_route_count = 0;
|
||||
}
|
||||
}
|
||||
fputs("OK\n", stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void destroy_map(HexMap* map){
|
||||
// Va a deallocare la mappa
|
||||
|
||||
|
||||
for (int i = 0; i < map -> cols && map -> grid[i]; i++) {
|
||||
free(map->grid[i]);
|
||||
}
|
||||
free(map->grid);
|
||||
map->grid = NULL;
|
||||
map->rows = map->cols = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void print_map(HexMap* map){
|
||||
printf("\n");
|
||||
for (int i=map->rows-1; i>=0; i--){ // Per ogni riga (se pari la offsetta per ottenere forma esagonale)
|
||||
if(i%2==1) printf(" ");
|
||||
for (int j=0; j<map -> cols; j++){ // Per ogni colonna
|
||||
printf("%d ",map -> grid[j][i].land_cost); // Stampa il costo dell'esagono'
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool is_valid(HexMap* map, int x, int y){
|
||||
if(x<0 || x>map->cols-1 || y<0 || y>map->rows-1){
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int hexagons_distance(int x_1, int y_1, int x_2, int y_2){
|
||||
// Viene usato per calcolare la distanza tra due esagoni (tramite coordinate cubiche)
|
||||
|
||||
|
||||
// Converte (x, y) in coordinate cubiche (cx, cy, cz)
|
||||
int cx1 = x_1 - (y_1 - (y_1 & 1)) / 2;
|
||||
int cz1 = y_1;
|
||||
int cy1 = -cx1 - cz1;
|
||||
|
||||
int cx2 = x_2 - (y_2 - (y_2 & 1)) / 2;
|
||||
int cz2 = y_2;
|
||||
int cy2 = -cx2 - cz2;
|
||||
|
||||
return fmax(fabs(cx1 - cx2), fmax(fabs(cy1 - cy2), fabs(cz1 - cz2))); // Ritorno la distanza tra i due esagoni
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void change_cost(HexMap* map, int x, int y, int cost, int radius){
|
||||
// Controllo che l'esagono sia valido
|
||||
if(!is_valid(map, x, y) || radius<=0 || cost < -10 || cost > 10){
|
||||
fputs("KO\n", stdout);
|
||||
fflush(stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Per ogni esagono in griglia, controllo se dista meno del raggio e, nel caso, gli calbio il costo
|
||||
int dist;
|
||||
int cost_old_air_route;
|
||||
float coeff;
|
||||
for(int i=0; i<map->cols; i++){
|
||||
for (int j=0; j<map->rows; j++){
|
||||
dist=hexagons_distance(x,y,i,j);
|
||||
if (dist<radius){
|
||||
if(((float)(radius - dist) / (float)radius)>0){ // Calcolo del coefficiente (fidati)
|
||||
coeff=((float)(radius - dist) / (float)radius);
|
||||
} else {
|
||||
coeff=0;
|
||||
}
|
||||
|
||||
map->grid[i][j].land_cost=map->grid[i][j].land_cost+(int)floor(cost * coeff); // Aggiorna il costo
|
||||
|
||||
|
||||
if (map -> grid[i][j].land_cost>100){ // Faccio il controllo sul costo (può essere compreso tra 0 e 100)
|
||||
map -> grid[i][j].land_cost=100;
|
||||
}
|
||||
if (map -> grid[i][j].land_cost<0){
|
||||
map -> grid[i][j].land_cost=0;
|
||||
}
|
||||
|
||||
|
||||
// Aggiorno i costi delle rotte aeree
|
||||
for (int counter=0; counter<map -> grid[i][j].air_route_count;counter++){
|
||||
cost_old_air_route=0;
|
||||
for (int n=0; n<counter;n++){
|
||||
cost_old_air_route=cost_old_air_route + map->grid[i][j].air_routes[n].cost;
|
||||
}
|
||||
map->grid[i][j].air_routes[counter].cost=(int)((cost_old_air_route+map->grid[i][j].land_cost)/(counter+1));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fputs("OK\n", stdout);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void toggle_air_route(HexMap* map, int x_1, int y_1, int x_2, int y_2){
|
||||
// FUNZIONAMENTO:
|
||||
// Analizzo l'array delle rotte aeree dell'esagono di partenza (x_1, y_1) e, se la rotta è già presente la elimino (rimuovo dall'array); se invece non è presente
|
||||
// la aggiungo (inserisco nell'array)
|
||||
|
||||
// Controllo che gli esagoni siano validi
|
||||
if(!is_valid(map, x_1,y_1) || !is_valid(map, x_2,y_2)){
|
||||
fputs("KO\n", stdout);
|
||||
fflush(stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Hexagon* StartingHexagon = &(map -> grid[x_1][y_1]); // Memorizzo il puntatore all'esagono di partenza
|
||||
|
||||
|
||||
// Controllo di non avere più di 5 rotte aeree (uso il 4 per come è costruito il codice)
|
||||
if (StartingHexagon -> air_route_count>4){
|
||||
fputs("KO\n", stdout);
|
||||
fflush(stdout);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i< StartingHexagon -> air_route_count; i++){ // Per ogni elemento all'interno della lista di rotte aeree dell'esagono di partenza
|
||||
if ((StartingHexagon -> air_routes[i].dest_x == x_2)&&(StartingHexagon -> air_routes[i].dest_y == y_2)){ // Se la rotta è già presente
|
||||
for (int j=i; j<StartingHexagon -> air_route_count; j++){ // Lo elimino shiftando gli elementi successivi a sx (così da non avere buchi nell'array)
|
||||
StartingHexagon -> air_routes[j]=StartingHexagon -> air_routes[j+1];
|
||||
}
|
||||
StartingHexagon -> air_route_count = StartingHexagon -> air_route_count - 1; // Diminuisco il contatore di rotte aeree
|
||||
fputs("OK\n", stdout);
|
||||
fflush(stdout);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Se sono arrivato qua, significa che la rotta non era presente nell'array e quindi la aggiungo
|
||||
// Calcolo il costo della rotta aerea
|
||||
int cost;
|
||||
if (StartingHexagon -> air_route_count==0){
|
||||
cost = (int) floor(StartingHexagon -> land_cost / ((StartingHexagon -> air_route_count)+1));
|
||||
} else {
|
||||
int sum=0;
|
||||
for (int i=0; i< StartingHexagon -> air_route_count; i++){
|
||||
sum = sum + (int) StartingHexagon -> air_routes[i].cost;
|
||||
}
|
||||
cost = (int) floor((int) (sum+(StartingHexagon -> land_cost)) / ((StartingHexagon -> air_route_count)+1));
|
||||
}
|
||||
|
||||
StartingHexagon -> air_routes[StartingHexagon -> air_route_count] = (AirRoute) {x_2, y_2, cost}; // Aggiungo la tratta all'array
|
||||
StartingHexagon -> air_route_count = StartingHexagon -> air_route_count + 1; // Aumento il contatore del numero di tratte
|
||||
fputs("OK\n", stdout);
|
||||
fflush(stdout);
|
||||
|
||||
|
||||
|
||||
// DEBUGGING
|
||||
/*
|
||||
* printf("Tratta aggiunta\n");
|
||||
* printf("La lista di tratte aeree partendo da %d %d:\n", x_1, y_1);
|
||||
* for (int i=0; i< StartingHexagon -> air_route_count; i++){
|
||||
* printf("x:%d y:%d costo:%d\n", StartingHexagon -> air_routes[i].dest_x, StartingHexagon -> air_routes[i].dest_y, StartingHexagon -> air_routes[i].cost);
|
||||
}
|
||||
printf("\n\n");
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
// END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// BEGIN HASH-TABLE
|
||||
|
||||
|
||||
// BEGIN STRUTTURE
|
||||
|
||||
typedef struct HashNode HashNode;
|
||||
|
||||
struct HashNode{
|
||||
int x,y;
|
||||
int distance_from_start;
|
||||
HashNode* next;
|
||||
};
|
||||
|
||||
|
||||
typedef struct{
|
||||
int size;
|
||||
HashNode** buckets;
|
||||
} HashTable;
|
||||
|
||||
|
||||
// END
|
||||
|
||||
|
||||
HashTable* create_hash_table(int size){
|
||||
// Riceve la dimensione della tabella esagonale e crea una hash table di dimensioni adeguate
|
||||
|
||||
|
||||
// Trovo la dimensione minima che deve avere la tabella (fattore di carico massimo 1.5)
|
||||
int min_size = (int)ceil(size / 1.5);
|
||||
|
||||
// Numeri primi buoni per dimensioni di hash table
|
||||
static const int primes[] = {
|
||||
53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
|
||||
49157, 98317, 196613, 393241, 786433, 1572869, 3145739,
|
||||
6291469, 12582917, 25165843, 50331653, 100663319, 201326611
|
||||
};
|
||||
|
||||
|
||||
// Trova il primo numero primo >= min_size che sarà la dimensione della tabella hash
|
||||
int hash_length=0;
|
||||
for (size_t i = 0; i < 23; i++) {
|
||||
if (primes[i] >= min_size) {
|
||||
hash_length = primes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Allco la struttura principale della hash table e inizializzo i suoi attributi
|
||||
HashTable* ht = (HashTable*)malloc(sizeof(HashTable));
|
||||
ht->size = hash_length;
|
||||
|
||||
|
||||
// Alloco l'array di bucket (li inizializzo tutti a NULL)
|
||||
ht->buckets = (HashNode**) malloc(hash_length * sizeof(HashNode*));
|
||||
for (int i = 0; i < hash_length; i++) {
|
||||
ht->buckets[i] = NULL;
|
||||
}
|
||||
|
||||
|
||||
return ht;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void clear_hash_table(HashTable* ht) {
|
||||
// Ripulisce la tabella dagli HashNode per poterla riutilizzare
|
||||
|
||||
|
||||
// Scorri tutti i bucket
|
||||
for (int i = 0; i < ht->size; i++) {
|
||||
HashNode* current = ht->buckets[i];
|
||||
|
||||
// Libera tutti i nodi nella catena
|
||||
while (current != NULL) {
|
||||
HashNode* next = current->next;
|
||||
free(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
// Reimposta il bucket a NULL
|
||||
ht->buckets[i] = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void destroy_hash_table(HashTable** ht) {
|
||||
// Distrugge completamente l'hash table
|
||||
|
||||
// Ripulisce tutti i nodi nella tabella
|
||||
clear_hash_table(*ht);
|
||||
|
||||
// Pulisce l'array dei bucket, la struttura principale e infine imposta a null il puntatore alla hash table
|
||||
free((*ht)->buckets);
|
||||
free(*ht);
|
||||
*ht = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void print_hash_table (HashTable* ht){
|
||||
|
||||
for (int i=0; i<(ht->size); i++){
|
||||
HashNode* current = ht->buckets[i];
|
||||
printf("Index[%d]: ", i);
|
||||
|
||||
while (current != NULL) {
|
||||
printf("[x:%d y:%d dist:%d]-> ", current -> x, current -> y, current -> distance_from_start);
|
||||
current = current->next;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int calculate_hash(int x, int y, int size){
|
||||
// Hash function
|
||||
|
||||
|
||||
const int p1 = 7919; // Primo grande
|
||||
const int p2 = 1237; // Altro primo grande
|
||||
|
||||
return ((x * p1) ^ (y * p2)) % size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool insert_or_update_element (HashTable* ht, int x, int y, int distance_from_start){
|
||||
// Cerca un nodo dalla hash table, se non lo trova lo aggiunge, mentre se lo trova aggiorna (se necessario) la distance_from_start
|
||||
// Ritorna true se il nodo è stato aggiunto o aggiornato, false altrimenti
|
||||
|
||||
|
||||
int index = calculate_hash(x, y, ht -> size); // Calcolo l'hash
|
||||
|
||||
|
||||
HashNode* current = ht -> buckets[index]; //Scorro la lista fino a quando trovo il nodo o la finisco
|
||||
while (current != NULL && !(current -> x == x && current -> y == y)){
|
||||
current = current -> next;
|
||||
}
|
||||
|
||||
if (current == NULL){ // Se non c'è il nodo, lo inserisco
|
||||
HashNode* hn = malloc(sizeof(HashNode)); // Crea il nodo con i parametri che sono stati passati alla funzione (l'attributo next lo definisco nell'inserimento in testa)
|
||||
hn->x = x;
|
||||
hn->y = y;
|
||||
hn->distance_from_start = distance_from_start;
|
||||
|
||||
|
||||
hn -> next = ht -> buckets[index]; // Inserisco in testa alla lista
|
||||
ht -> buckets[index] = hn;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (current -> distance_from_start > distance_from_start){ // Se c'è già, se posso lo aggiorno
|
||||
current -> distance_from_start = distance_from_start;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int search_element (HashTable* ht, int x, int y){
|
||||
// Cerca un nodo dalla hash table e ne restituisce il costo
|
||||
|
||||
|
||||
int index = calculate_hash(x, y, ht -> size); // Calcolo l'hash
|
||||
|
||||
|
||||
HashNode* current = ht -> buckets[index]; //Scorro la lista fino a quando trovo il nodo o la finisco
|
||||
while (current != NULL && !(current -> x == x && current -> y == y)){
|
||||
current = current -> next;
|
||||
}
|
||||
|
||||
if(current==NULL){ // Se il nodo non è presente, restituisce -1
|
||||
return -1;
|
||||
}
|
||||
|
||||
return current->distance_from_start;
|
||||
}
|
||||
|
||||
|
||||
// END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// BEGIN PATH-FINDING (Dijkstra)
|
||||
|
||||
|
||||
// BEGIN STRUTTURE
|
||||
|
||||
typedef struct {
|
||||
int x,y;
|
||||
int distance_from_start;
|
||||
} QueueNode_PathFinding;
|
||||
|
||||
// END
|
||||
|
||||
|
||||
void enqueue(QueueNode_PathFinding* queue, HashTable* ht, int x, int y, int node_cost, int head, int tail){
|
||||
// Controllo il costo del nodo x,y in hash table e se il valore che trovo è minore di quello che gli passo, non aggiungo in coda (non vale la pena aggiungere il percorso con un costo maggiore)
|
||||
int hn_cost = search_element(ht, x, y);
|
||||
if (node_cost >= hn_cost){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int temp_cost;
|
||||
for (int i=head; i<tail; i++) {
|
||||
temp_cost = queue[i].distance_from_start; // Trovo il costo del nodo i-esimo nella coda
|
||||
|
||||
if(node_cost < temp_cost){ // Se il nodo da inserire costa meno del nodo i-esimo della coda
|
||||
for (int j=tail; j>=i; j--){ // Sposto tutti i nodi successivi avanti di uno
|
||||
queue[j+1]=queue[j];
|
||||
}
|
||||
queue[i]=(QueueNode_PathFinding) {x, y, node_cost}; // Inserisco il nodo nella coda in posizione i
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
queue[tail]=(QueueNode_PathFinding) {x, y}; // Se non è stato aggiunto in mezzo alla coda, lo devo aggiungere alla fine
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int travel_cost(HexMap* map, HashTable* ht, int xp, int yp, int xd, int yd){
|
||||
// FUNZIONAMENTO:
|
||||
// È un algoritmo Dijkstra in cui tengo sempre una coda ORDINATA che ha in testa le coordinate x,y del nodo con minore costo, mentre in coda quello con maggior costo.
|
||||
// Il costo è dato dalla distanza dal nodo sorgente
|
||||
//
|
||||
// Inizializzo la coda e ci inserisco il nodo sorgente; una volta fatto questo inserisco i 6 nodi vicini nella hashtable e poi nella coda.
|
||||
//
|
||||
// NOTA: la funzione di inserimento dell'hash table inserisce il costo solamente se è minore di quello già presente e riotrna true solo se il nodo viene aggiunto o aggiornato
|
||||
// (se il costo è maggiore di quello precedente, ritorna false).
|
||||
//
|
||||
// NOTA: la funzione di inserimento in coda inserisce i nodi già ordinandoli in base al loro costo.
|
||||
|
||||
|
||||
if (!is_valid(map,xp,yp) || !is_valid(map,xd,yd)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO realloc dinamica della coda
|
||||
int queue_dimension = map->rows * map->cols * sizeof(QueueNode_PathFinding)*100; // Inizializzo la coda con dimensione 100 x del numero di nodi, head e tail
|
||||
QueueNode_PathFinding* queue = malloc(queue_dimension);
|
||||
int head=0;
|
||||
int tail=0;
|
||||
|
||||
|
||||
queue[0] = (QueueNode_PathFinding) {xp, yp, 0}; // Inserisco il nodo sorgente in coda
|
||||
tail++;
|
||||
insert_or_update_element(ht, xp, yp, 0); // Inserisco il nodo sorgente in hash table
|
||||
|
||||
|
||||
QueueNode_PathFinding current; // Inizializzo current, ossia il primo nodo della coda su cui lavoro (quello con costo minore dato che la coda è ordinata)
|
||||
int current_cost; // Il costo di current in coda
|
||||
int current_ht_cost; // Inizializzo current_ht_cost, ossia il costo del nodo nell'hash table corrispondente a current
|
||||
|
||||
int new_x; // new_x e new_y vengono usate per immagazzinare i 6 nodi vicini
|
||||
int new_y;
|
||||
|
||||
int air_route_count; // In queste due variabili vado a inserire gli attributi delle rotte aeree del nodo corrente
|
||||
AirRoute* air_routes;
|
||||
|
||||
|
||||
while (head<tail){
|
||||
// ISPEZIONO IL PRIMO NODO DELLA CODA
|
||||
current=queue[head]; // Definisco current
|
||||
current_cost=current.distance_from_start; // Definisco il costo di current
|
||||
head++;
|
||||
current_ht_cost = search_element(ht, current.x, current.y); // Cerco current nella hash table e il costo corrispondente lo metto in current_ht_cost (NOTA: current sarà sicuramente nell'hash table)
|
||||
|
||||
|
||||
// Se il nodo che sto ispezionando non è quello con il costo dell'hash table, vado alla prossima iterazione del qhile (quello con costo minore o è già stato ispezionato oppure è in hash table)
|
||||
if (current.distance_from_start > current_ht_cost){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ISPEZIONI I VICINI
|
||||
if(map->grid[current.x][current.y].land_cost!=0){ // Se current è transitabile
|
||||
|
||||
// ISPEZIONI I 6 VICINI
|
||||
// Creo i due percorsi da ispezionare in base alla riga (pari o dispari)
|
||||
const int dir_even[6][2] = {
|
||||
{+1, 0}, { 0, -1}, {+1, -1},
|
||||
{-1, 0}, {+1, +1}, { 0, +1}
|
||||
};
|
||||
const int dir_odd[6][2] = {
|
||||
{+1, 0}, {-1, -1}, { 0, -1},
|
||||
{-1, 0}, { 0, +1}, {-1, +1}
|
||||
};
|
||||
|
||||
|
||||
// Scelgo la direzione in base alla parità della riga
|
||||
const int (*dirs)[2] = (current.y % 2 == 1) ? dir_even : dir_odd;
|
||||
|
||||
|
||||
// Guardo le coordinate dei 6 nodi vicini (per ogni iterazione, il nodo vicino avrà coordinate new_x, new_y)
|
||||
for (int i = 0; i < 6; i++) {
|
||||
new_x = current.x + dirs[i][0];
|
||||
new_y = current.y + dirs[i][1];
|
||||
|
||||
|
||||
if(is_valid(map, new_x, new_y)){ // Se il nodo è nella mappa
|
||||
if (insert_or_update_element(ht, new_x, new_y, current_ht_cost+map->grid[current.x][current.y].land_cost)){ // Se inserendolo ottengo true
|
||||
enqueue(queue, ht, new_x, new_y, current_cost, head, tail); // Lo aggiungo alla coda
|
||||
tail++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ISPEZIONI LE ROTTE AEREE USCENTI DA CURRENT
|
||||
air_route_count=map->grid[current.x][current.y].air_route_count;
|
||||
air_routes=map->grid[current.x][current.y].air_routes;
|
||||
|
||||
for (int i=0; i<air_route_count; i++){
|
||||
new_x=air_routes[i].dest_x; // La destinazione la memorizzo in new_x e new_y (come l'inserimento dei 6 nodi vicini)
|
||||
new_y=air_routes[i].dest_y;
|
||||
|
||||
|
||||
if(is_valid(map, new_x, new_y)){ // Se il nodo è nella mappa
|
||||
if (insert_or_update_element(ht, new_x, new_y, current_ht_cost+air_routes[i].cost)){ // Se inserendolo ottengo true
|
||||
enqueue(queue, ht, new_x, new_y, current_cost, head, tail); // Lo aggiungo alla coda
|
||||
tail++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ris = search_element(ht, xd, yd);
|
||||
free(queue); // Dealloco la coda
|
||||
clear_hash_table(ht); // Pulisco la hash table
|
||||
return ris;
|
||||
}
|
||||
|
||||
|
||||
// END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(){
|
||||
|
||||
char testo[30];
|
||||
int inp_uno, inp_due, inp_tre, inp_quattro;
|
||||
|
||||
HexMap map;
|
||||
HashTable* ht = NULL;
|
||||
|
||||
int already_initialized=0;
|
||||
|
||||
while (1){
|
||||
|
||||
// LEGGO L'INPUT E SE RAGGIUNGO L'EOF FACCIO UNA BREAK
|
||||
int tmp_input = scanf("%s %d %d %d %d",testo, &inp_uno, &inp_due, &inp_tre, &inp_quattro);
|
||||
if (tmp_input==-1){
|
||||
break;
|
||||
}
|
||||
if (strcmp(testo, "init")==0){
|
||||
|
||||
// MAPPA
|
||||
if (already_initialized==1){
|
||||
destroy_map(&map);
|
||||
}
|
||||
init_map(&map, inp_uno, inp_due);
|
||||
already_initialized=1;
|
||||
|
||||
// HASH TABLE
|
||||
if (ht!=NULL){
|
||||
destroy_hash_table(&ht);
|
||||
}
|
||||
ht = create_hash_table(inp_uno * inp_due);
|
||||
}
|
||||
if (strcmp(testo, "print")==0){
|
||||
print_map(&map);
|
||||
}
|
||||
if (strcmp(testo, "change_cost")==0){
|
||||
change_cost(&map, inp_uno, inp_due, inp_tre, inp_quattro);
|
||||
clear_hash_table(ht);
|
||||
}
|
||||
if (strcmp(testo, "toggle_air_route")==0){
|
||||
toggle_air_route(&map, inp_uno, inp_due, inp_tre, inp_quattro);
|
||||
}
|
||||
if (strcmp(testo, "travel_cost")==0){
|
||||
int costo = travel_cost(&map, ht, inp_uno, inp_due, inp_tre, inp_quattro);
|
||||
fprintf(stdout, "%d\n", costo);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user