void CRUELstart() { int i, j, k; list ll = LISTinit(), q; /* inicializa as 4 pilhas de naipes */ for( i = 0; i < 4; i++ ) { suitStack[i] = STACKinit( 13 ); LISTaddStart( ll, CARDcreate( i, 1 ) ); } /* aleatoriza a ordem das 4 pilhas de naipes */ for( i = 0; i < 4; i++ ) { k = rand() % (4 - i); q = LISTgetNterm( ll, k ); STACKpush( &suitStack[i], LISTgetVal(q) ); suitPosition[ CARDsuit(LISTgetVal(q)) ] = i; LISTremove(q); } /* inicializa as 12 pilhas de cartas */ for( i = 0; i < 12; i++ ) cardStack[i] = STACKinit( 26 ); /* coloca as 48 cartas na lista ligada */ for( j = 0; j < 4; j++ ) { for( i = 2; i <= 13; i++ ) { LISTaddStart( ll, CARDcreate( j, i ) ); } } /* preechemos as 12 pilhas de cartas linearmente, mas com cartas escolhidas aleatoriamente */ for( i = 0; i < 12; i++ ) { for( j = 0; j < 4; j++ ) { k = rand() % (48 - (4 * i + j) ); q = LISTgetNterm( ll, k ); STACKpush( &cardStack[i], LISTgetVal(q) ); LISTremove(q); } } LISTdestroy(ll); /* Selecionar uma carta aleatoria. Como funciona: Coloca-se todas as cartas numa LL. Sempre que precisar de uma carta aleatoria, fazer k = rand() % TOTAL_DE_CARTAS_NA_LL e pegar a k-esima carta da LL, removendo-a da lista. */ cardLeft = 48; movedSinceDist = 0; lastSugest = ACTIONcreate(-1,-1,-1); }
void CRUELredistribute() { list ll = LISTinit(), q; int j = 0, i = 0; while( i < 12 ) { if( STACKempty( cardStack[i] ) ) i++; else LISTaddEnd( ll, STACKpop( &cardStack[i] ) ); } i = 0; while( !LISTempty( ll ) ) { if( j >= 4 ) { j = 0; i++; } q = LISTgetNterm( ll, 3 - j ); if( q ) { STACKpush( &cardStack[i], LISTgetVal( q ) ); LISTremove(q); } j++; } LISTdestroy(ll); movedSinceDist = 0; lastSugest = ACTIONcreate(-1,-1,-1); }
/*Destroi a entidade passada, liberando a memoria usada por ela.*/ void destroiEntidade(Entity ent) { /*Remove uma entidade da lista que seja considerada igual a ent, de acordo com a funcao de comparacao passada.*/ LISTremove(entityList, ent, compareEntities, _freeEntity ); ent = NULL; }
void* CiclistaThread(void* arg) { /* This is our thread. There are many like it, this one is ours. */ ciclista c = (ciclista) arg; double vel; int tempo_gasto_trecho_atual = 0; /* Ciclista ja terminou a corrida. Nao corre mais poar. */ while(c->km < tamanho_estrada) { /* Espera o ciclo começar. */ sem_wait(&c->continua_ciclo); if(modo_simula) { char tipo = c->trecho_atual ? ((trecho)c->trecho_atual->val)->tipo : ((trecho)trechos->first->val)->tipo; switch(tipo) { case 'P': vel = c->vel_plano; break; case 'S': vel = c->vel_subida; break; case 'D': vel = c->vel_descida; break; default: vel = 0.0; } } else { vel = c->vel_plano; } c->tempo_gasto_total += CICLO_TIME; tempo_gasto_trecho_atual += CICLO_TIME; c->metros += kmh2ms(vel) * CICLO_TIME; /* Precisa mudar de KM? */ if(c->metros >= 1000) { /* Estou terminando a corrida? */ if(c->km + 1 >= tamanho_estrada) { /* YEAH TERMINEI! */ /* Pega lock pra colocar na lista dos que terminaram. */ pthread_mutex_lock(&terminar_mutex); LISTaddEnd(ciclistas_terminaram, c); pthread_mutex_unlock(&terminar_mutex); /* Pega lock para se tirar da lista de quem tava no ultimo km. Esse lock também me permite modificar a lista do trecho, que termina nesse mesmo km. */ pthread_mutex_lock( &estrada[c->km].mutex); LISTremove(estrada[c->km].ciclistas, c); /* Eu certamente terminei o último trecho. */ c->tempo[c->numero_trecho_atual] = tempo_gasto_trecho_atual; tempo_gasto_trecho_atual = 0; LISTaddOrder(((trecho) trechos->last->val)->checkpoint_ranking, c, lessOperation); (c->numero_trecho_atual)++; pthread_mutex_unlock(&estrada[c->km].mutex); c->km++; c->metros -= 1000; } else { /* Pega lock para Ler e possívelmente escrever no próximo KM. */ pthread_mutex_lock(&estrada[c->km + 1].mutex); if(LISTsize(estrada[c->km + 1].ciclistas) < largura_estrada) { /* Opa, consegui entrar no proximo km, to rox. */ LISTaddEnd(estrada[c->km + 1].ciclistas, c); pthread_mutex_unlock(&estrada[c->km + 1].mutex); c->kms_no_trecho++; if(c->km >= 0) { trecho trecho_atual = (trecho) c->trecho_atual->val; /* Se eu não estou no limbo de começo de corrida... 1. vou me tirar da lista do km anterior. Preciso travar o mutex senão da merda. 2. Preciso ver se eu estou terminando algum trecho. -> Se sim, o mesmo lock do km me permite mexer nesse mutex. */ pthread_mutex_lock( &estrada[c->km].mutex); LISTremove(estrada[c->km].ciclistas, c); if(c->kms_no_trecho == trecho_atual->distancia) { /* Opa, terminei o meu trecho! :D */ c->tempo[c->numero_trecho_atual] = tempo_gasto_trecho_atual; tempo_gasto_trecho_atual = 0; LISTaddOrder(trecho_atual->checkpoint_ranking, c, lessOperation); (c->numero_trecho_atual)++; c->trecho_atual = c->trecho_atual->next; c->kms_no_trecho = 0; } pthread_mutex_unlock(&estrada[c->km].mutex); } else { /* Estou começando a corrida agora. */ c->trecho_atual = trechos->first; c->kms_no_trecho = 0; } /* Tudo ok, atualiza variaveis. */ c->km++; c->metros -= 1000; } else { /* Fico parado esperando abrir espaço. Tomando cuidado pra não dormir. Tb libero o lock. */ pthread_mutex_unlock(&estrada[c->km + 1].mutex); c->metros = 1000; } } } sem_post(&c->terminou_ciclo); } return NULL; }