/*
* MAIN.C - ARQUIVO PRINCIPAL
* Projeto: Into the Abyss
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "lista.h"
#include "pilha.h"
#include "fila.h"
#include "entidade.h"
#include "item.h"
#include "jogador.h"
#include "baralho.h"
// ============================================================================
// FUNÇÕES AUXILIARES
// ============================================================================
int ler_input_seguro() {
char buffer[100];
char *fim_ptr;
while (1) {
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
buffer[strcspn(buffer, "\n")] = 0;
if (strlen(buffer) == 0) continue;
long valor = strtol(buffer, &fim_ptr, 10);
if (*fim_ptr == '\0') return (int)valor;
}
printf(" >> Entrada invalida! Digite um NUMERO: ");
}
}
void imprimir_lore(int id_evento, TipoClasse classe) {
printf("\n=== MEMORIA DO ABISMO ===\n");
if (id_evento == 1) {
switch(classe) {
case CLASSE_GUERREIRO: printf("\"Voce limpa o sangue da espada e seu reflexo no aço manchado o encara. \nVoce se pergunta se Eldraine o reconheceria assim, coberto pela sujeira do Abismo.\"\n"); break;
case CLASSE_NECROMANTE: printf("\"Voce passa por um tumulo improvisado. \nA imagem de sua mae, palida e doente, invade sua mente. \n'O poder de Aldous é profano... mas se for o preço para ve-la de novo?'\"\n"); break;
case CLASSE_SACERDOTE: printf("\"Vislumbres do simbolo de Aerion partido ao meio vem a sua mente. \nVoce sente o peso da fe... e o medo de que Eda sofra o mesmo destino.\"\n"); break;
case CLASSE_HUNTERS: printf("\"Wolf solta um ganido baixo. Voce o acalma, mas o cheiro de morte no ar o lembra do porque estão nessa. \nVoce tenta imaginar o cheiro do mar. \n'So mais um pouco...', voce sussurra.\"\n"); break;
default: break;
}
}
else if (id_evento == 2) {
switch(classe) {
case CLASSE_GUERREIRO: printf("\"Seu braco doi. Voce ve as veias escurecendo sob a pele, um eco da corrupcao de Aldous que destruiu seus ancestrais. Voce nao esta apenas lutando contra um Lich; esta lutando contra o destino de sua linhagem.\"\n"); break;
case CLASSE_NECROMANTE: printf("\"Ao tocar nas escrituras do seu tomo antigo, um sussurro gelido preenche sua mente. 'Eles tambem a deixaram morrer...' A voz nao e sua. Voce recua, assustada. A proximidade com o poder do Lich esta... chamando.\"\n"); break;
case CLASSE_SACERDOTE: printf("\"Voce sente a presenca de Lyssandra neste lugar. A visao de Aerion retorna: 'Sua necromancia pode ser a porta. Nao deixe que ela seja aberta.'\"\n"); break;
case CLASSE_HUNTERS: printf("\"Wolf comeca a tremer. A corrupcao do Abismo o esta afetando. Voce escuta sons distantes. Se voce nao se cuidar, talvez tenha que escolher entre seu amigo e sua propria vida.\"\n"); break;
default: break;
}
}
else if (id_evento == 3) {
switch(classe) {
case CLASSE_GUERREIRO: printf("\"'Nao importa', voce pensa. 'Eu nao volto como um soldado pedindo. Eu volto como o heroi que ela merece.'\"\n"); break;
case CLASSE_NECROMANTE: printf("\"Aldous está proximo. Voce sente a vibraçao do poder. Voce ve sua mae sorrindo, saudavel. Seria uma ilusao? Ou uma promessa? Voce percebe que nao se importa mais. Voce vai descobrir o segredo, custe o que custar.\"\n"); break;
case CLASSE_SACERDOTE: printf("\"A luz de Aerion mal penetra aqui. A fe e sua unica armadura. Voce se lembra do juramento: purificar o Abismo. Nao ha mais duvida. Aldous deve cair, ou Eda caira com você.\"\n"); break;
case CLASSE_HUNTERS: printf("\"Voce sente uma brisa semelhante ao mar passar por voce. O contraste parece brutal. Esta nao e mais uma caçada por dinheiro. Voce tem que sair daqui para sentir o sol nascer sobre suas peles.\"\n"); break;
default: break;
}
}
printf("=========================\n");
}
void imprimir_final_vitoria(TipoClasse classe) {
printf("\n========================================\n");
printf(" VITORIA SUPREMA! \n");
printf("========================================\n");
switch(classe) {
case CLASSE_GUERREIRO:
printf("Alex limpa o sangue de sua lamina. O Lich caiu.\n");
printf("Voce retorna como o Salvador de Eda e estende a mao para Eldraine.\n");
printf("A honra do cla Draven foi restaurada, e um novo legado começa.\n");
break;
case CLASSE_NECROMANTE:
printf("Nas cinzas do Lich, voce encontra a paz que buscava.\n");
printf("Sua mae nao volta a vida, mas voce finalmente entende a morte.\n");
printf("Voce deixa o Abismo, sabia e livre da sombra que a perseguia.\n");
break;
case CLASSE_SACERDOTE:
printf("Thamus sente o calor de Aerion. Voce se tornou o Avatar da Chama Branca.\n");
printf("O Abismo foi purificado e sua fe junto, Eda esta a salva por enquanto.\n");
break;
case CLASSE_HUNTERS:
printf("O silencio reina. Ronan escuta os uivo alegre de Wolf, ambos vivos e com apenas um destino.\n");
printf("Semanas depois... voce esta sentado na areia da praia, sentindo o nascer do sol sob sua pele. Sua casa finalmente recem construída atrás de você e com Wolf correndo atrás de alguns siris. A vida de caça acabou.\n");
break;
default: break;
}
printf("\nPARABENS! Voce completou INTO THE ABYSS.\n");
}
void imprimir_final_derrota(TipoClasse classe) {
printf("\n========================================\n");
printf(" FINAL TRAGICO... \n");
printf("========================================\n");
switch(classe) {
case CLASSE_GUERREIRO:
printf("A corrupção do Abismo invade suas feridas, envenenando sua alma até que apenas obediência ao Lich permaneça.\n");
printf("Eldraine chorará sua queda, incapaz de imaginar que você renasceu como o general sombrio que selará o destino de Eda.\n");
break;
case CLASSE_NECROMANTE:
printf("A voz de Aldous ri: 'A eterna morte.' Voce servira ao Lich usando seus poderes para reviver os mortos pela eternidade.\n");
break;
case CLASSE_SACERDOTE:
printf("Onde havia chamas, agora so resta o frio. O reino caira e voce não terá como impedir essa tragedia.\n");
break;
case CLASSE_HUNTERS:
printf("Ronan cai ao lado de Wolf; o ultimo ganido do lobo parte seu coracao. Os pes que um dia sentiram a areia agora tocam apenas o frio do Abismo, e a brisa do mar se torna so um eco distante..\n");
printf("Os sonhos de uma casa na praia, jamais construida, se desfazem nas sombras. A escuridao os engole por completo. O Abismo nao deixa sobreviventes.\n");
break;
default: break;
}
printf("\nGAME OVER.\n");
}
// --- INVENTÁRIO ---
void menu_inventario(Jogador* j) {
if (lista_tamanho(j->inventario) == 0) {
printf("\n>> Inventario vazio.\n");
return;
}
printf("\n--- INVENTARIO ---\n");
NoLista* atual = j->inventario->cabeca;
int idx = 0;
Item* itens_temp[50];
while (atual != NULL) {
Item* i = (Item*)atual->dados;
itens_temp[idx] = i;
printf("%d. %s ", idx+1, i->nome);
// Exibe o status correto do item
char bonus_str[20];
switch(i->status_afetado) {
case STATUS_DANO: strcpy(bonus_str, "Dano"); break;
case STATUS_DEFESA: strcpy(bonus_str, "Def"); break;
case STATUS_ATAQUE: strcpy(bonus_str, "Atk"); break;
case STATUS_HP: strcpy(bonus_str, "HP Max"); break;
default: strcpy(bonus_str, "Especial"); break;
}
if (i->tipo == ITEM_ARMA) printf("[Arma: +%d %s]", i->valor, bonus_str);
else if (i->tipo == ITEM_ARMADURA) printf("[Armadura: +%d %s]", i->valor, bonus_str);
else if (i->tipo == ITEM_ALIADO) printf("[Aliado: %s]", i->descricao);
else if (i->tipo == ITEM_POCAO) printf("[Pocao: +%d %s]", i->valor, bonus_str);
if (i == j->arma_equipada) printf(" <EQUIPADO>");
if (i == j->armadura_equipada) printf(" <VESTIDO>");
if (i == j->aliado_equipado) printf(" <ATIVO>");
printf("\n");
atual = atual->proximo;
idx++;
}
printf("\nDigite o numero para Equipar/Usar (0 para sair): ");
int esc = ler_input_seguro();
if (esc > 0 && esc <= idx) {
Item* alvo = itens_temp[esc-1];
if (alvo->tipo == ITEM_POCAO) jogador_usar_pocao(j, alvo);
else jogador_equipar_item(j, alvo);
}
}
// --- COMBATE ---
int combate_executar(Jogador* j, Entidade* monstro) {
printf("\n========================================\n");
printf("!!! COMBATE: %s (Nv %d) !!!", monstro->nome, monstro->nivel);
printf("\n========================================\n");
printf("INIMIGO -> HP: %d | Def: %d | Dano: %d\n",
monstro->hp_max, monstro->defesa, monstro->dano_base);
Fila* turno = fila_criar();
fila_enqueue(turno, j->base);
for(int k=0; k < monstro->nivel; k++) fila_enqueue(turno, monstro);
int fugiu = 0;
int vitoria = 0;
j->base->buff_dano = 0;
while(!fila_vazia(turno)) {
Entidade* atual = (Entidade*)fila_dequeue(turno);
if (atual->hp_atual <= 0) continue;
if (j->base->hp_atual <= 0) break;
if (monstro->hp_atual <= 0) { vitoria = 1; break; }
// TURNO JOGADOR
if (atual == j->base) {
printf("\n[SEU TURNO] HP: %d/%d", j->base->hp_atual, jogador_calcular_hp_max_total(j));
// Habilidade Aliado Sacerdote
if (j->aliado_equipado && strstr(j->aliado_equipado->nome, "Sacerdote")) {
int max_hp = jogador_calcular_hp_max_total(j);
if (j->base->hp_atual < max_hp) {
j->base->hp_atual += 5;
printf(" (Sacerdote curou +5 HP)");
}
}
printf("\n");
// Habilidade Aliado Necromante
if (j->aliado_equipado && strstr(j->aliado_equipado->nome, "Necromante")) {
monstro->hp_atual -= 3;
printf(">> Aliado Necromante drenou –3 HP do inimigo!\n");
if (monstro->hp_atual <= 0) { vitoria = 1; break; }
}
int dano_total = jogador_calcular_dano_total(j);
int atk_bonus = jogador_calcular_ataque_total(j);
printf("Stats: Acerto +%d | Dano %d\n", atk_bonus, dano_total);
printf("1. Atacar\n2. Inventario/Pocao\n3. Fugir\n> ");
int acao = ler_input_seguro();
if (acao == 1) {
// Habilidade Caçador: Ataque Duplo
int ataques = (j->base->classe == CLASSE_HUNTERS) ? 2 : 1;
for (int i = 0; i < ataques; i++) {
if (monstro->hp_atual <= 0) break;
if (i > 0) printf("\n>> HABILIDADE CAÇADORES: Ataque Coordenado! \nVoce ataca novamente\n");
int dados = rolar_dados();
int final = dados + atk_bonus;
printf(">> Ataque %d: Rolou %d + %d = %d (Def: %d)... \n", i+1, dados, atk_bonus, final, monstro->defesa);
if (final >= monstro->defesa) {
monstro->hp_atual -= dano_total;
printf("ACERTOU! %d de dano.\n", dano_total);
// Habilidade Necromante: Toque Mortífero
if (j->base->classe == CLASSE_NECROMANTE) {
j->base->hp_atual += dano_total / 3;
int toque_mortifero = dano_total / 3;
int max = jogador_calcular_hp_max_total(j);
if (j->base->hp_atual > max) j->base->hp_atual = max;
printf(">> HABILIDADE NECROMANTE: Toque Mortífero! \nVoce recupera %d de vida (+%d HP)\n", toque_mortifero, toque_mortifero);
}
} else {
printf("ERROU!\n");
}
}
} else if (acao == 2) {
menu_inventario(j);
} else if (acao == 3) {
printf(">> Voce fugiu!\n");
fugiu = 1; break;
}
}
// TURNO MONSTRO
else {
printf("\n[%s ATACA]\n", monstro->nome);
int dados = rolar_dados();
int final = dados + monstro->ataque;
int def_jog = jogador_calcular_defesa_total(j);
printf(">> Inimigo: Rolou %d + %d = %d (Sua Def: %d)... \n", dados, monstro->ataque, final, def_jog);
if (final >= def_jog) {
int dano_sofrido = monstro->dano_base;
// Habilidade Guerreiro: Resistência
if (j->base->classe == CLASSE_GUERREIRO) {
dano_sofrido -= def_jog / 4;
int resistencia = def_jog / 4;
if (dano_sofrido < 0) dano_sofrido = 0;
printf("HABILIDADE GUERREIRO: Resistência! \nVoce reduziu o dano recebido em –%d ", resistencia);
}
j->base->hp_atual -= dano_sofrido;
printf("ATINGIDO! Sofreu %d de dano.\n", dano_sofrido);
} else {
printf("BLOQUEADO!\n");
}
}
if (atual->hp_atual > 0) fila_enqueue(turno, atual);
}
j->base->buff_dano = 0;
fila_destruir(turno);
if (fugiu) return 0;
if (vitoria) {
printf("\n>> VOCE DERROTOU %s!\n", monstro->nome);
// Habilidade Sacerdote: Benção de Aerion
if (j->base->classe == CLASSE_SACERDOTE) {
j->base->hp_atual += j->base->hp_max / 3;
int bencao_aerion = j->base->hp_max / 3;
int max = jogador_calcular_hp_max_total(j);
if (j->base->hp_atual > max) j->base->hp_atual = max;
printf(">> HABILIDADE SACERDOTE: Benção de Aerion! \nVoce cura +%d HP.\n", bencao_aerion);
}
return 1;
}
return 0;
}
// --- MAIN ---
int main() {
srand(time(NULL));
char nome[50];
printf("================================================\n");
printf(" INTO THE ABYSS \n");
printf("================================================\n");
printf("Digite seu nome: ");
fgets(nome, 49, stdin);
nome[strcspn(nome, "\n")] = 0;
printf("\nHá muito tempo, o Rei Aldous desceu ao Abismo \npara selar as Aberrações, criaturas que \nnascem da própria ferida do mundo. \nPara vencê-las, ele recorreu à magia proibida, \nsacrificando seu proprio corpo e alma.\n");
printf("\nAgora Aldous desperta como um Lich, e seu \nrenascimento ameaça consumir todo reino Eda. \nPor ordem do Rei Delmondes, por juramentos \nou simplesmente suas próprias ambições.\n");
printf("\nQuatro aventureiros escolheram descer até o abismo \npara impedir que o antigo salvador retorne como \no fim do reino que uma vez jurou proteger.\n");
printf("\nEscolha sua Classe:\n");
printf("1. O Guerreiro (Alex Draven)\n");
printf("2. A Necromante (Lyssandra Valle)\n");
printf("3. O Sacerdote (Thamus da Casa Solaris)\n");
printf("4. Os Caçadores (Ronan e Wolf)\n");
printf("> ");
int op_classe = ler_input_seguro();
TipoClasse classe = CLASSE_GUERREIRO;
if (op_classe == 2) classe = CLASSE_NECROMANTE;
if (op_classe == 3) classe = CLASSE_SACERDOTE;
if (op_classe == 4) classe = CLASSE_HUNTERS;
Jogador* jogador = jogador_criar(nome, classe);
printf("\nO Abismo esta sendo gerado... Embaralhando 53 cartas...\n");
Pilha* dungeon = baralho_criar_dungeon(classe);
pilha_embaralhar(dungeon);
int jogando = 1;
while (jogando && jogador->base->hp_atual > 0) {
// HUD ATUALIZADO
int atk = jogador_calcular_ataque_total(jogador);
int def = jogador_calcular_defesa_total(jogador);
int dano = jogador_calcular_dano_total(jogador);
int max_hp = jogador_calcular_hp_max_total(jogador);
printf("\n--------------------------------------------------\n");
printf("%s | Cartas: %d | Coringas: %d/2\n", jogador->nome_jogador, jogador->cartas_compradas, jogador->coringas_encontrados);
printf("HP: %d/%d | Def: %d | Acerto: +%d | Dano: %d\n", jogador->base->hp_atual, max_hp, def, atk, dano);
printf("--------------------------------------------------\n");
printf("1. Explorar\n2. Inventario\n");
if (jogador->coringas_encontrados >= 2) printf("3. !!! BOSS: LICH ALDOUS !!!\n");
printf("0. Desistir\n> ");
int opcao = ler_input_seguro();
if (opcao == 0){
printf("\nVoce corre atormentado pela escuridão, \napenas com aquela sensação de fracasso, \no abismo é so para os fortes!!!");
break;
}
else if (opcao == 2) menu_inventario(jogador);
else if (opcao == 3 && jogador->coringas_encontrados >= 2) {
Entidade* boss = entidade_criar("LICH REI ALDOUS", CLASSE_MONSTRO, 60, 8, 14, 8, 3);
if (combate_executar(jogador, boss)) {
imprimir_final_vitoria(classe);
jogando = 0;
} else {
imprimir_final_derrota(classe);
jogando = 0;
}
entidade_liberar(boss);
}
else if (opcao == 1) {
if (pilha_tamanho(dungeon) == 0) {
printf("\nO baralho acabou! Voce ficou preso... dentro do Abismo!\n");
break;
}
Carta* carta = (Carta*)pilha_pop(dungeon);
jogador->cartas_compradas++;
printf("\n[CARTA %d] >> %s\n", jogador->cartas_compradas, carta->nome_carta);
switch (carta->tipo_efeito) {
case EFEITO_MONSTRO:
if (!combate_executar(jogador, carta->monstro_associado)) {
imprimir_final_derrota(classe);
jogando = 0;
}
break;
case EFEITO_ITEM:
printf(">> Voce encontrou um item!\n");
Item* ni = item_criar(carta->item_associado->nome, carta->item_associado->tipo, carta->item_associado->status_afetado, carta->item_associado->valor, carta->item_associado->descricao);
jogador_adicionar_item(jogador, ni);
break;
case EFEITO_EVENTO_CURA:
printf(">> Uma luz fraca e avermelhada surge no corredor. Um espírito benevolente toca seu ombro, curando suas feridas antes de desaparecer! \nVocê recupera +5 HP\n");
jogador->base->hp_atual += 5;
if(jogador->base->hp_atual > max_hp) jogador->base->hp_atual = max_hp;
break;
case EFEITO_EVENTO_DANO:
printf(">> Você pisa em uma placa de pressão solta e ouve um 'clique'. Uma lâmina de veneno passa raspando por você! Você se esquiva, mas ainda sofre dano! \nVoce perde –3 HP\n");
jogador->base->hp_atual -= 3;
break;
case EFEITO_EVENTO_LORE:
imprimir_lore(carta->id_evento, jogador->base->classe);
break;
case EFEITO_EVENTO_GATO:
printf("Você ouve um miado fraco. Encolhido em um canto está um pequeno gato preto. Ele esfrega na sua perna, mia mais uma vez, e corre para a escuridão. Você se sente... estranhamente observado!\n");
break;
case EFEITO_EVENTO_PIADA:
printf(">> Uma mulher surge da escuridão, ela aparenta vestir as mesmas roupas de outros ocultistas fanáticos e desaparece na escuridão.\n");
break;
case EFEITO_EVENTO_PIADA_2:
printf(">> Uma figura misteriosa surge da escuridão, ela pronúncia palavras incompreensíveis e some ao seu piscar de olhos.\n");
break;
case EFEITO_EVENTO_OURO:
printf(">> Você encontra o corpo de um aventureiro que não teve sorte. Ao lado dele, uma bolsa pesada de moedas. Pelo menos a jornada dele não foi em vão!\n");
break;
case EFEITO_BOSS_KEY:
printf("\n!!! FILACTERIA DO LICH ENCONTRADO !!!\n");
printf("\nVOCE OBTEVE UMA DAS DUAS ESSÊNCIAS DO LICH\n");
jogador->coringas_encontrados++;
break;
default: printf(">> Evento de ambiente estranho...\n"); break;
}
carta_liberar(carta);
}
}
if (jogador->base->hp_atual <= 0 && jogando == 1) imprimir_final_derrota(classe);
jogador_destruir(jogador);
pilha_destruir(dungeon, carta_liberar);
return 0;
}
#ifndef LISTA_H
#define LISTA_H
// Nó genérico para a lista encadeada
typedef struct NoLista {
void* dados;
struct NoLista* proximo;
} NoLista;
// O TAD Lista
typedef struct {
NoLista* cabeca;
int tamanho;
} Lista;
// --- Funções ---
Lista* lista_criar();
void lista_destruir(Lista* l, void (*free_dados)(void*));
void lista_inserir(Lista* l, void* dados); // Insere no início
void* lista_remover(Lista* l, void* dados); // Remove um item específico
void* lista_buscar_indice(Lista* l, int indice); // Retorna o dado no índice X
int lista_tamanho(Lista* l);
#endif
#ifndef PILHA_H
#define PILHA_H
#include "lista.h"
// A Pilha reutiliza a estrutura da Lista
typedef Lista Pilha;
// --- Funções ---
Pilha* pilha_criar();
void pilha_destruir(Pilha* p, void (*free_dados)(void*));
void pilha_push(Pilha* p, void* dados); // Empilha (põe no topo)
void* pilha_pop(Pilha* p); // Desempilha (tira do topo)
int pilha_tamanho(Pilha* p);
void pilha_embaralhar(Pilha* p); // Função especial para "baralhar" a pilha
#endif
#ifndef FILA_H
#define FILA_H
typedef struct NoFila {
void* dados;
struct NoFila* proximo;
} NoFila;
typedef struct {
NoFila* inicio;
NoFila* fim;
int tamanho;
} Fila;
// --- Funções ---
Fila* fila_criar();
void fila_destruir(Fila* f); // Não libera os dados internos, só a estrutura
void fila_enqueue(Fila* f, void* dados); // Entra na fila
void* fila_dequeue(Fila* f); // Sai da fila
int fila_vazia(Fila* f);
#endif
#ifndef ENTIDADE_H
#define ENTIDADE_H
typedef enum {
CLASSE_GUERREIRO,
CLASSE_NECROMANTE,
CLASSE_SACERDOTE,
CLASSE_HUNTERS,
CLASSE_MONSTRO
} TipoClasse;
typedef struct {
char nome[50];
TipoClasse classe;
int nivel; // Nível para definir quantos ataques por rodada a entidade pode fazer
int hp_atual; // Vida atual da classe
int hp_max; // Vida máxima da classe
int ataque; // Bônus para acertar (2d6 + ataque)
int defesa; // Classe de Armadura
int dano_base; // Dano fixo causado ao acertar
int buff_dano; // Dano temporário (Poção de Fúria)
char acao_descricao[100];
} Entidade;
// Função atualizada
Entidade* entidade_criar(const char* nome, TipoClasse classe, int hp, int atk, int def, int dano, int nivel);
void entidade_liberar(void* dados);
int rolar_dados(); // simula a rolagem usando o rand de 2d6
void entidade_imprimir_status(Entidade* e);
#endif
#ifndef ITEM_H
#define ITEM_H
typedef enum {
ITEM_ARMA,
ITEM_ARMADURA,
ITEM_POCAO,
ITEM_ALIADO,
ITEM_ESPECIAL
} TipoItem;
// NOVO ENUM: Define qual status o item melhora
typedef enum {
STATUS_DANO, // Aumenta o dano causado
STATUS_DEFESA, // Aumenta a defesa (bloqueio)
STATUS_ATAQUE, // Aumenta o acerto (2d6 + x)
STATUS_HP, // Aumenta a Vida Máxima
STATUS_NENHUM // Para itens sem bonus passivo
} TipoStatus;
typedef struct {
char nome[50];
char descricao[100];
TipoItem tipo;
TipoStatus status_afetado; // NOVO CAMPO
int valor;
int id_carta;
} Item;
// Função atualizada para receber o status
Item* item_criar(const char* nome, TipoItem tipo, TipoStatus status, int valor, const char* desc);
void item_liberar(void* dados);
#endif
#ifndef JOGADOR_H
#define JOGADOR_H
#include "entidade.h"
#include "lista.h"
#include "item.h"
typedef struct {
Entidade* base; // Status base (HP, Classe)
char nome_jogador[50];
Lista* inventario; // Lista de itens coletados
// Equipamentos Atuais (Ponteiros para itens dentro do inventário)
Item* arma_equipada;
Item* armadura_equipada;
Item* aliado_equipado;
int coringas_encontrados; // Precisa de 2 para o Boss
int cartas_compradas; // Ranking (score)
} Jogador;
// --- Funções de Criação e Destruição ---
Jogador* jogador_criar(const char* nome, TipoClasse classe_escolhida);
void jogador_destruir(Jogador* j);
// --- Gestão de Inventário ---
void jogador_adicionar_item(Jogador* j, Item* i);
void jogador_equipar_item(Jogador* j, Item* i);
void jogador_usar_pocao(Jogador* j, Item* i);
// --- Cálculos de Status (Protótipos que faltavam) ---
int jogador_calcular_hp_max_total(Jogador* j); // <--- ESTE ERA O QUE FALTAVA
int jogador_calcular_dano_total(Jogador* j);
int jogador_calcular_ataque_total(Jogador* j);
int jogador_calcular_defesa_total(Jogador* j);
#endif
#ifndef BARALHO_H
#define BARALHO_H
#include "pilha.h"
#include "entidade.h"
#include "item.h"
// Naipes e Valores do Baralho
typedef enum { ESPADAS, PAUS, OUROS, COPAS, CORINGA_NAIPE } Naipe;
typedef enum {
VALOR_2 = 2, VALOR_3, VALOR_4, VALOR_5, VALOR_6,
VALOR_7, VALOR_8, VALOR_9, VALOR_10,
VALOR_J = 11, // Valete (Poção)
VALOR_Q = 12, // Dama (Arma)
VALOR_K = 13, // Rei (Armadura)
VALOR_A = 14, // Ás (Aliado/Classe)
VALOR_CORINGA_VAL = 0 // Especial
} ValorCarta;
// O que esta carta faz quando comprada?
typedef enum {
EFEITO_MONSTRO, // Inicia combate
EFEITO_ITEM, // Item melhora atributo
EFEITO_EVENTO_LORE, // Contar a história
EFEITO_EVENTO_CURA, // Cura o jogador
EFEITO_EVENTO_DANO, // Armadilha
EFEITO_EVENTO_OURO, // Narrativo
EFEITO_EVENTO_GATO, // Narrativo
EFEITO_EVENTO_PIADA, // Narrativo
EFEITO_EVENTO_PIADA_2, // Narrativo
EFEITO_BOSS_KEY // Coringa
} TipoEfeito;
// Estrutura da Carta
typedef struct {
Naipe naipe;
ValorCarta valor;
char nome_carta[50]; // Ex: "Ás de Espadas"
TipoEfeito tipo_efeito;
// Dados associados (apenas um destes será usado dependendo do efeito)
Entidade* monstro_associado; // Se for monstro (cria na hora de processar)
Item* item_associado; // Se for item
int id_evento; // ID para lore/piada
} Carta;
// --- Funções ---
// Cria o baralho completo (54 cartas), removendo a classe que o jogador escolheu
Pilha* baralho_criar_dungeon(TipoClasse classe_jogador);
// Processa o efeito da carta (cria o monstro, dá o item, mostra o texto)
void carta_processar_efeito(Carta* c, void* estado_jogo);
// Libera a memória da carta
void carta_liberar(void* dados);
#endif
#include <stdio.h>
#include <stdlib.h>
#include "lista.h"
// Cria o "cabeçalho" da lista, que gerencia o primeiro elemento e o tamanho.
Lista* lista_criar() {
Lista* l = (Lista*)malloc(sizeof(Lista));
if (l) {
l->cabeca = NULL; // Lista começa vazia
l->tamanho = 0;
}
return l;
}
//Limpa toda a memória da lista.
void lista_destruir(Lista* l, void (*free_dados)(void*)) {
if (!l) return;
NoLista* atual = l->cabeca;
while (atual != NULL) {
NoLista* temp = atual;
atual = atual->proximo; // Salva o próximo antes de destruir o atual
// Se a função de limpeza foi fornecida, limpa o dado interno
if (free_dados && temp->dados) {
free_dados(temp->dados);
}
free(temp); // Libera o nó
}
free(l); // Libera a estrutura de controle
}
//Adiciona um elemento no início (cabeça) da lista
void lista_inserir(Lista* l, void* dados) {
if (!l) return;
NoLista* novo = (NoLista*)malloc(sizeof(NoLista));
novo->dados = dados;
novo->proximo = l->cabeca; // O novo nó aponta para onde o início (cabeça) apontava
// A cabeça agora é o novo nó
l->cabeca = novo;
l->tamanho++;
}
//Procura um ponteiro de dados específico e o remove da lista.
void* lista_remover(Lista* l, void* dados) {
if (!l || !l->cabeca) return NULL;
NoLista* atual = l->cabeca;
NoLista* ant = NULL; // Rastrea o anterior para recosturar a lista
// Procura o dado percorrendo a lista
while (atual != NULL && atual->dados != dados) {
ant = atual;
atual = atual->proximo;
}
if (!atual) return NULL; // Caso chegou no fim e não achou o item
// Se o item estava no início (cabeça)
if (!ant) {
l->cabeca = atual->proximo;
}
// Se estava no meio ou fim
else {
ant->proximo = atual->proximo; //Pula o nó atual
}
void* ret = atual->dados; // Guarda o dado para retornar
free(atual); // Libera só o nó
l->tamanho--;
return ret;
}
// Acessa a lista como se fosse um vetor
// Usado no menu de inventário para selecionar o item "1", "2", etc.
void* lista_buscar_indice(Lista* l, int indice) {
if (!l || indice < 0 || indice >= l->tamanho) return NULL;
NoLista* atual = l->cabeca;
// Caminha N vezes até chegar no índice desejado
for (int i = 0; i < indice; i++) {
atual = atual->proximo;
}
return atual->dados;
}
int lista_tamanho(Lista* l) {
return l ? l->tamanho : 0;
}
#include <stdio.h>
#include <stdlib.h>
#include "pilha.h"
Pilha* pilha_criar() {
return lista_criar(); // Reutiliza Lista
}
void pilha_destruir(Pilha* p, void (*free_dados)(void*)) {
lista_destruir(p, free_dados);
}
void pilha_push(Pilha* p, void* dados) {
lista_inserir(p, dados);
}
void* pilha_pop(Pilha* p) {
if (!p || p->tamanho == 0) return NULL;
// Remove o primeiro elemento (topo)
// Como lista_remover precisa do ponteiro do dado, usamos um truque:
// pegamos o dado do topo e mandamos remover.
void* dados = p->cabeca->dados;
return lista_remover(p, dados);
}
int pilha_tamanho(Pilha* p) {
return lista_tamanho(p);
}
// Algoritmo de Fisher-Yates para embaralhar a lista encadeada
void pilha_embaralhar(Pilha* p) {
if (!p || p->tamanho < 2) return;
int n = p->tamanho;
void** array_temp = (void**)malloc(n * sizeof(void*));
// 1. Copia tudo para um array temporário
NoLista* atual = p->cabeca;
for (int i = 0; i < n; i++) {
array_temp[i] = atual->dados;
atual = atual->proximo;
}
// 2. Embaralha o array
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1);
void* temp = array_temp[i];
array_temp[i] = array_temp[j];
array_temp[j] = temp;
}
// 3. Devolve para a lista na nova ordem
atual = p->cabeca;
for (int i = 0; i < n; i++) {
atual->dados = array_temp[i];
atual = atual->proximo;
}
free(array_temp);
}
#include <stdio.h>
#include <stdlib.h>
#include "fila.h"
Fila* fila_criar() {
Fila* f = (Fila*)malloc(sizeof(Fila));
// Se a alocação funcionou (f não é NULL)
if (f) {
f->inicio = NULL; // A fila começa sem ninguém
f->fim = NULL; // A fila termina sem ninguém
f->tamanho = 0; // Contador zerado
}
return f;
}
void fila_destruir(Fila* f) {
if (!f) return; // Se a fila não existe, não faz nada
NoFila* atual = f->inicio;
// Percorre toda a fila liberando nó por nó
while (atual != NULL) {
NoFila* temp = atual; // Guarda o nó atual para apagar depois
atual = atual->proximo; // Avança para o próximo antes de apagar
free(temp); // Libera a memória do nó
}
free(f);
}
void fila_enqueue(Fila* f, void* dados) {
if (!f) return;
// Cria um novo nó para carregar os dados
NoFila* novo = (NoFila*)malloc(sizeof(NoFila));
novo->dados = dados;
novo->proximo = NULL; // já que é o último, não aponta para ninguém
// Verifica se a fila estava vazia
if (f->fim == NULL) {
// Se estava vazia, o novo elemento é tanto o início quanto o fim
f->inicio = novo;
} else {
// Se já tinha gente, o antigo último agora aponta para o novo
f->fim->proximo = novo;
}
// Atualiza o ponteiro de fim para ser o novo nó
f->fim = novo;
f->tamanho++;
}
void* fila_dequeue(Fila* f) {
// Verifica se a fila existe ou se está vazia
if (!f || f->inicio == NULL) return NULL;
// Pega o nó que está na ponta da fila
NoFila* temp = f->inicio;
void* dados = temp->dados; // Salva o conteúdo (Jogador/Monstro) para retornar depois
// Avança o início da fila para o segundo da lista
f->inicio = f->inicio->proximo;
// Se a fila ficou vazia após a remoção
if (f->inicio == NULL) {
f->fim = NULL; // O fim também deve ser NULL
}
free(temp);
f->tamanho--;
return dados; // Indica quem é a vez no sistema de combate
}
int fila_vazia(Fila* f) {
return (f == NULL || f->tamanho == 0);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "item.h"
// Atualizado com TipoStatus
Item* item_criar(const char* nome, TipoItem tipo, TipoStatus status, int valor, const char* desc) {
Item* i = (Item*)malloc(sizeof(Item));
strncpy(i->nome, nome, 49);
strncpy(i->descricao, desc, 99);
i->tipo = tipo;
i->status_afetado = status; // Salva o tipo de bônus
i->valor = valor;
i->id_carta = 0;
return i;
}
void item_liberar(void* dados) {
free(dados);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "entidade.h"
Entidade* entidade_criar(const char* nome, TipoClasse classe, int hp, int atk, int def, int dano, int nivel) {
Entidade* e = (Entidade*)malloc(sizeof(Entidade));
strncpy(e->nome, nome, 49);
e->classe = classe;
e->hp_max = hp;
e->hp_atual = hp;
e->ataque = atk;
e->defesa = def;
e->dano_base = dano; // Novo campo
e->buff_dano = 0; // Começa zerado
e->nivel = nivel;
strcpy(e->acao_descricao, "ataca");
return e;
}
void entidade_liberar(void* dados) {
free(dados);
}
int rolar_dados() {
return (rand() % 6 + 1) + (rand() % 6 + 1); // 2d6
}
void entidade_imprimir_status(Entidade* e) {
printf("[%s] HP: %d/%d | ATK: +%d | DEF: %d | DANO: %d\n",
e->nome, e->hp_atual, e->hp_max, e->ataque, e->defesa, e->dano_base);
}
/*
* JOGADOR.C
* Gerencia status e cálculos
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jogador.h"
Jogador* jogador_criar(const char* nome, TipoClasse classe_escolhida) {
Jogador* j = (Jogador*)malloc(sizeof(Jogador));
strncpy(j->nome_jogador, nome, 49);
j->inventario = lista_criar();
j->arma_equipada = NULL;
j->armadura_equipada = NULL;
j->aliado_equipado = NULL;
j->coringas_encontrados = 0;
j->cartas_compradas = 0;
// --- VALORES BASE ---
int hp, atk, def, dano;
switch (classe_escolhida) {
case CLASSE_GUERREIRO: hp = 24; atk = 4; def = 11; dano = 6; break;
case CLASSE_NECROMANTE: hp = 18; atk = 3; def = 10; dano = 15; break;
case CLASSE_SACERDOTE: hp = 36; atk = 3; def = 10; dano = 4; break;
case CLASSE_HUNTERS: hp = 21; atk = 4; def = 11; dano = 5; break;
}
j->base = entidade_criar(nome, classe_escolhida, hp, atk, def, dano, 1);
return j;
}
// Função destrutora: Evita Memory Leaks
void jogador_destruir(Jogador* j) {
if (!j) return;
entidade_liberar(j->base);
lista_destruir(j->inventario, item_liberar);
free(j);
}
void jogador_adicionar_item(Jogador* j, Item* i) {
lista_inserir(j->inventario, i);
printf(">> Item obtido: %s (%s)\n", i->nome, i->descricao);
}
void jogador_equipar_item(Jogador* j, Item* i) {
if (i->tipo == ITEM_ARMA) {
j->arma_equipada = i;
printf(">> Voce equipou a arma: %s\n", i->nome);
} else if (i->tipo == ITEM_ARMADURA) {
j->armadura_equipada = i;
printf(">> Voce equipou a armadura: %s\n", i->nome);
} else if (i->tipo == ITEM_ALIADO) {
j->aliado_equipado = i;
printf(">> %s agora esta te ajudando!\n", i->nome);
}
}
void jogador_usar_pocao(Jogador* j, Item* i) {
if (i->tipo != ITEM_POCAO) return;
if (strstr(i->nome, "Furia") != NULL) {
printf(">> Voce bebeu a POCAO DE FURIA! (+3 Dano neste combate)\n");
j->base->buff_dano += 3;
} else {
printf(">> Voce bebeu a POCAO DE VIDA! (+10 HP)\n");
j->base->hp_atual += 10;
// Verifica se passou do Max HP calculado
int max_hp = jogador_calcular_hp_max_total(j);
if (j->base->hp_atual > max_hp)
j->base->hp_atual = max_hp;
}
lista_remover(j->inventario, i);
item_liberar(i);
}
// --- CÁLCULOS DINÂMICOS ---
int jogador_calcular_hp_max_total(Jogador* j) {
int total = j->base->hp_max;
// Soma itens que dão HP
if (j->arma_equipada && j->arma_equipada->status_afetado == STATUS_HP)
total += j->arma_equipada->valor;
if (j->armadura_equipada && j->armadura_equipada->status_afetado == STATUS_HP)
total += j->armadura_equipada->valor;
return total;
}
int jogador_calcular_dano_total(Jogador* j) {
int total = j->base->dano_base;
// Soma itens que dão Dano
if (j->arma_equipada && j->arma_equipada->status_afetado == STATUS_DANO)
total += j->arma_equipada->valor;
if (j->armadura_equipada && j->armadura_equipada->status_afetado == STATUS_DANO)
total += j->armadura_equipada->valor;
// Aliado Guerreiro
if (j->aliado_equipado && strstr(j->aliado_equipado->nome, "Guerreiro"))
total += 3;
total += j->base->buff_dano;
return total;
}
int jogador_calcular_ataque_total(Jogador* j) {
int total = j->base->ataque;
// Soma itens que dão Ataque (Acerto)
if (j->arma_equipada && j->arma_equipada->status_afetado == STATUS_ATAQUE)
total += j->arma_equipada->valor;
if (j->armadura_equipada && j->armadura_equipada->status_afetado == STATUS_ATAQUE)
total += j->armadura_equipada->valor;
// Aliado Caçador
if (j->aliado_equipado && strstr(j->aliado_equipado->nome, "Caçador"))
total += 3;
return total;
}
int jogador_calcular_defesa_total(Jogador* j) {
int total = j->base->defesa;
// Soma itens que dão Defesa
if (j->arma_equipada && j->arma_equipada->status_afetado == STATUS_DEFESA)
total += j->arma_equipada->valor;
if (j->armadura_equipada && j->armadura_equipada->status_afetado == STATUS_DEFESA)
total += j->armadura_equipada->valor;
return total;
}
/*
* BARALHO.C
* Responsável por criar o deck e definir os atributos dos itens/monstros
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "baralho.h"
Carta* criar_carta_vazia(Naipe n, ValorCarta v) {
Carta* c = (Carta*)malloc(sizeof(Carta));
c->naipe = n;
c->valor = v;
c->monstro_associado = NULL;
c->item_associado = NULL;
c->tipo_efeito = EFEITO_EVENTO_LORE;
return c;
}
void configurar_carta_numerica(Carta* c) {
c->tipo_efeito = EFEITO_MONSTRO;
// MONSTROS NIVEL 1 (HP, ATK, DEF, DANO)
// Goblin: 10, 3, 10, 3
// Soldado: 14, 3, 11, 4
// Cultista: 12, 4, 10, 4
// Aranha: 13, 4, 9, 5
// MONSTROS NIVEL 2 (HP, ATK, DEF, DANO)
// Demonio: 22, 6, 12, 6
// Servo: 20, 5, 13, 6
// Amalgama: 26, 4, 11, 7
// Aberracao: 24, 5, 10, 8
// Espadas/Paus = Foco em combate
if (c->naipe == ESPADAS) {
switch(c->valor) {
case VALOR_2:
c->monstro_associado = entidade_criar("Goblin", CLASSE_MONSTRO, 10, 2, 10, 3, 1); break;
case VALOR_3:
c->monstro_associado = entidade_criar("Goblin Reanimado", CLASSE_MONSTRO, 12, 4, 9, 3, 1); break;
case VALOR_4: case VALOR_5:
c->monstro_associado = entidade_criar("Soldado Reanimado", CLASSE_MONSTRO, 14, 3, 11, 4, 1); break;
case VALOR_6:
c->monstro_associado = entidade_criar("Líder do Culto", CLASSE_MONSTRO, 16, 3, 10, 3, 2); break;
case VALOR_7:
c->monstro_associado = entidade_criar("Aranha Gigante", CLASSE_MONSTRO, 13, 4, 9, 5, 1); break;
case VALOR_8:
c->monstro_associado = entidade_criar("Demonio da Escuridao", CLASSE_MONSTRO, 20, 5, 12, 6, 2); break;
case VALOR_9:
c->monstro_associado = entidade_criar("Servo Leal do Lich", CLASSE_MONSTRO, 24, 6, 13, 6, 2); break;
case VALOR_10:
c->monstro_associado = entidade_criar("Amalgama Viva", CLASSE_MONSTRO, 24, 4, 10, 7, 2); break;
default: break;
}
}
else if (c->naipe == PAUS) {
switch(c->valor) {
case VALOR_2: c->monstro_associado = entidade_criar("Goblin", CLASSE_MONSTRO, 10, 2, 10, 3, 1); break;
case VALOR_3: case VALOR_4: c->monstro_associado = entidade_criar("Cultista", CLASSE_MONSTRO, 13, 2, 9, 3, 1); break;
case VALOR_5: c->monstro_associado = entidade_criar("Aranha Gigante", CLASSE_MONSTRO, 13, 4, 9, 5, 1); break;
case VALOR_6: c->monstro_associado = entidade_criar("Soldado Reanimado", CLASSE_MONSTRO, 14, 3, 11, 4, 1); break;
case VALOR_7: c->monstro_associado = entidade_criar("Demonio da Escuridao", CLASSE_MONSTRO, 20, 5, 12, 6, 2); break;
case VALOR_8: c->monstro_associado = entidade_criar("Aberracao", CLASSE_MONSTRO, 26, 4, 11, 8, 2); break;
case VALOR_9: c->monstro_associado = entidade_criar("Servo Leal do Lich", CLASSE_MONSTRO, 24, 6, 13, 6, 2); break;
case VALOR_10: c->tipo_efeito = EFEITO_EVENTO_DANO;
strcat(c->nome_carta, " (Armadilha de Espinhos) "); break;
default: break;
}
}
else if (c->naipe == OUROS) {
switch(c->valor) {
case VALOR_2: c->monstro_associado = entidade_criar("Cultista", CLASSE_MONSTRO, 13, 2, 9, 3, 1); break;
case VALOR_3: case VALOR_8: c->tipo_efeito = EFEITO_EVENTO_OURO; strcat(c->nome_carta, " (Ouro Perdido) "); break;
case VALOR_4: c->monstro_associado = entidade_criar("Soldado Reanimado", CLASSE_MONSTRO, 14, 3, 11, 4, 1); break;
case VALOR_5: case VALOR_9: c->tipo_efeito = EFEITO_EVENTO_DANO; strcat(c->nome_carta, " (Armadilha Oculta) "); break;
case VALOR_6: c->monstro_associado = entidade_criar("Demonio da Escuridao", CLASSE_MONSTRO, 20, 5, 12, 6, 2); break;
case VALOR_7: c->tipo_efeito = EFEITO_EVENTO_GATO; strcat(c->nome_carta, " (Gato Preto) "); break;
case VALOR_10: c->monstro_associado = entidade_criar("Amalgama Viva", CLASSE_MONSTRO, 24, 4, 10, 7, 2); break;
default: break;
}
}
else if (c->naipe == COPAS) {
if(c->valor == 7) {
c->monstro_associado = entidade_criar("Aberracao", CLASSE_MONSTRO, 26, 4, 11, 8, 2);
} else if (c->valor >= 8) {
c->tipo_efeito = EFEITO_EVENTO_LORE;
c->id_evento = c->valor - 7;
strcat(c->nome_carta, " (Memórias do Abismo) ");
} else if (c->valor == 5) {
c->tipo_efeito = EFEITO_EVENTO_PIADA;
strcat(c->nome_carta, " (Figura Estranha) ");
} else if (c->valor == 6){
c->tipo_efeito = EFEITO_EVENTO_PIADA_2;
strcat(c->nome_carta, " (Vulto Misterioso) ");
}else {
c->tipo_efeito = EFEITO_EVENTO_CURA;
strcat(c->nome_carta, " (Espirito Protetor) ");
}
}
}
Pilha* baralho_criar_dungeon(TipoClasse classe_jogador) {
Pilha* baralho = pilha_criar();
for (int n = 0; n < 4; n++) {
// 1. Cartas Numéricas
for (int v = 2; v <= 10; v++) {
Carta* c = criar_carta_vazia((Naipe)n, (ValorCarta)v);
sprintf(c->nome_carta, "%d de %s", v, n==ESPADAS?"Espadas":n==PAUS?"Paus":n==OUROS?"Ouros":"Copas");
configurar_carta_numerica(c);
pilha_push(baralho, c);
}
// 2. Valetes (J) = Poções
Carta* cJ = criar_carta_vazia((Naipe)n, VALOR_J);
cJ->tipo_efeito = EFEITO_ITEM;
if (n == COPAS || n == OUROS) {
sprintf(cJ->nome_carta, "Valete de %s (Pocao Vida)", n==OUROS?"Ouros":"Copas");
cJ->item_associado = item_criar("Pocao de Vida", ITEM_POCAO, STATUS_HP, 10, "Cura 10 de Vida");
} else {
sprintf(cJ->nome_carta, "Valete de %s (Pocao Furia)", n==ESPADAS?"Espadas":"Paus");
cJ->item_associado = item_criar("Pocao de Furia", ITEM_POCAO, STATUS_DANO, 3, "+3 Dano Temporario");
}
pilha_push(baralho, cJ);
// 3. Damas (Q) = Armas (Status Variáveis por Naipe)
Carta* cQ = criar_carta_vazia((Naipe)n, VALOR_Q);
cQ->tipo_efeito = EFEITO_ITEM;
char nome_arma[50];
char desc_arma[100];
TipoStatus stat_arma;
int valor_arma = 3 + (n % 2); // 2 ou 3
if (n == ESPADAS) { // DANO
sprintf(nome_arma, "Espada Grande");
sprintf(desc_arma, "Concede +%d de DANO", valor_arma);
stat_arma = STATUS_DANO;
} else if (n == PAUS) { // DEFESA
sprintf(nome_arma, "Machado de Batalha");
sprintf(desc_arma, "Concede +%d de DEFESA", valor_arma);
stat_arma = STATUS_DEFESA;
} else if (n == OUROS) { // HP
sprintf(nome_arma, "Lança Vampirica");
sprintf(desc_arma, "Concede +%d de HP MAX", valor_arma * 3);
valor_arma *= 3;
stat_arma = STATUS_HP;
} else { // ATAQUE (Copas)
sprintf(nome_arma, "Adaga Refinada");
sprintf(desc_arma, "Concede +%d de ATAQUE (Acerto)", valor_arma);
stat_arma = STATUS_ATAQUE;
}
sprintf(cQ->nome_carta, "Dama de %s (%s)", n==ESPADAS?"Espadas":n==PAUS?"Paus":n==OUROS?"Ouros":"Copas", nome_arma);
cQ->item_associado = item_criar(nome_arma, ITEM_ARMA, stat_arma, valor_arma, desc_arma);
pilha_push(baralho, cQ);
// 4. Reis (K) = Armaduras (Status Variáveis por Naipe)
Carta* cK = criar_carta_vazia((Naipe)n, VALOR_K);
cK->tipo_efeito = EFEITO_ITEM;
char nome_armor[50];
char desc_armor[100];
TipoStatus stat_armor;
int valor_armor = 3 + (n % 2);
if (n == ESPADAS) { // DANO
sprintf(nome_armor, "Armadura de Espinhos");
sprintf(desc_armor, "Concede +%d de DANO", valor_armor);
stat_armor = STATUS_DANO;
} else if (n == PAUS) { // DEFESA
sprintf(nome_armor, "Armadura Reforçada");
sprintf(desc_armor, "Concede +%d de DEFESA", valor_armor);
stat_armor = STATUS_DEFESA;
} else if (n == OUROS) { // HP
sprintf(nome_armor, "Armadura Arcana");
sprintf(desc_armor, "Concede +%d de HP MAX", valor_armor * 3);
valor_armor *= 3;
stat_armor = STATUS_HP;
} else { // ATAQUE
sprintf(nome_armor, "Couro Leve");
sprintf(desc_armor, "Concede +%d de ATAQUE (Acerto)", valor_armor);
stat_armor = STATUS_ATAQUE;
}
sprintf(cK->nome_carta, "Rei de %s (%s)", n==ESPADAS?"Espadas":n==PAUS?"Paus":n==OUROS?"Ouros":"Copas", nome_armor);
cK->item_associado = item_criar(nome_armor, ITEM_ARMADURA, stat_armor, valor_armor, desc_armor);
pilha_push(baralho, cK);
// 5. Ases (A) = Aliados
if ((int)classe_jogador != n) {
Carta* cA = criar_carta_vazia((Naipe)n, VALOR_A);
cA->tipo_efeito = EFEITO_ITEM;
char nome_aliado[50];
char desc_aliado[100];
TipoStatus stat_aliado = STATUS_NENHUM;
switch(n) {
case CLASSE_GUERREIRO:
strcpy(nome_aliado, "Aliado Guerreiro");
strcpy(desc_aliado, "+3 de Dano passivo");
stat_aliado = STATUS_DANO;
break;
case CLASSE_NECROMANTE:
strcpy(nome_aliado, "Aliado Necromante");
strcpy(desc_aliado, "Drena 3 HP do inimigo por turno");
break;
case CLASSE_SACERDOTE:
strcpy(nome_aliado, "Aliado Sacerdote");
strcpy(desc_aliado, "Cura 5 HP por turno");
break;
case CLASSE_HUNTERS:
strcpy(nome_aliado, "Aliado Caçadores");
strcpy(desc_aliado, "+3 de Ataque passivo");
stat_aliado = STATUS_ATAQUE;
break;
}
sprintf(cA->nome_carta, "As de %s (%s)", n==ESPADAS?"Espadas":n==PAUS?"Paus":n==OUROS?"Ouros":"Copas", nome_aliado);
cA->item_associado = item_criar(nome_aliado, ITEM_ALIADO, stat_aliado, 2, desc_aliado);
pilha_push(baralho, cA);
}
}
// 6. Coringas
for(int i=0; i<2; i++) {
Carta* c = criar_carta_vazia(CORINGA_NAIPE, VALOR_CORINGA_VAL);
strcpy(c->nome_carta, "CORINGA - FILACTERIO DO LICH");
c->tipo_efeito = EFEITO_BOSS_KEY;
pilha_push(baralho, c);
}
return baralho;
}
void carta_liberar(void* dados) {
Carta* c = (Carta*)dados;
if (c->monstro_associado) entidade_liberar(c->monstro_associado);
if (c->item_associado) item_liberar(c->item_associado);
free(c);
}