
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#include <process.h>

/*グローバル変数の宣言*/
int tmp_HP;
int tmp_SA;
int tmp_SD;
int SA_counter = -1;
int SD_counter = -1;


/*ファイル操作失敗時*/
void MissFile(void)
{
	unsigned long int time_val;
	puts("ファイルが存在しないため情報の初期化に失敗しました。");
	puts("ファイルが実行ファイルと同じディレクトリ内にあるか確認してください。");
	puts("ファイルが見つからない場合はもう一度ダウンロードしてください。");
	puts(" 30 秒後に強制終了しますので手動で閉じないでください。");

	time_val = time(NULL);
	while(1) {
		if(time(NULL) - time_val == 30)
			exit(-1);
	}
}


/*主人公*/

//主人公の情報構造体
typedef struct {
	char name[30];
	short HP;
	unsigned short attack;
	unsigned short defence;
	unsigned short a_masic;
	unsigned short d_masic;
	unsigned short speed;
	unsigned int lvup_exp;
	unsigned long exp_value;
	unsigned short level;
	unsigned short max_level;
	unsigned short ability_level[3];
	unsigned short ability[5];
	unsigned short item[3][2];
}Hero;

/*グローバル変数の宣言*/
Hero hero;

//主人公の初期化
int InitHero(void)
{
	FILE *fp;

	fp = fopen("Hero_Status_Info.txt", "r");
	if(fp == NULL)
		return 0;

	fscanf(fp, "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
		&hero.name, &hero.HP, &hero.attack, &hero.defence, &hero.a_masic, &hero.d_masic,
		&hero.speed, &hero.lvup_exp, &hero.exp_value, &hero.level, &hero.max_level,
		&hero.ability_level[0], &hero.ability_level[1], &hero.ability_level[2],
		&hero.ability[0], &hero.ability[1], &hero.ability[2], &hero.ability[3],
		&hero.ability[4], &hero.item[0][0], &hero.item[0][1], &hero.item[1][0], &hero.item[1][1],
		&hero.item[2][0], &hero.item[2][1]);
	fclose(fp);

	return 1;
}

//主人公の情報を保存
int SaveHero(void)
{
	FILE *fp;

	fp = fopen("Hero_Status_Info.txt", "w");
	if(fp == NULL)
		return 0;

	fprintf(fp, "%s\n\n%d\n%d\n%d\n%d\n%d\n%d\n\n%d\n%d\n%d\n%d\n\n%d\n%d\n%d\n\n%d\n%d\n%d\n%d\n%d\n\n%d\n%d\n%d\n%d\n%d\n%d",
		hero.name, hero.HP, hero.attack, hero.defence, hero.a_masic, hero.d_masic,
		hero.speed, hero.lvup_exp, hero.exp_value, hero.level, hero.max_level,
		hero.ability_level[0], hero.ability_level[1], hero.ability_level[2],
		hero.ability[0], hero.ability[1], hero.ability[2], hero.ability[3],
		hero.ability[4], hero.item[0][0], hero.item[0][1], hero.item[1][0], hero.item[1][1],
		hero.item[2][0], hero.item[2][1]);
	fclose(fp);

	return 1;
}


/*敵*/

//敵の基本情報構造体
typedef struct {
	char name[20];
	unsigned short enemy_num;
	unsigned short if_boss;
	short HP;
	unsigned short attack;
	unsigned short defence;
	unsigned short a_masic;
	unsigned short d_masic;
	unsigned short speed;
	unsigned short ability;
}Enemy;

/*グローバル変数の宣言*/
Enemy pawn;
Enemy knight;
Enemy bishop;
Enemy rook;
Enemy queen;
Enemy king;

//各敵を初期化
int InitEnemy(Enemy *enemy, char *file_name)
{
	FILE *fp;

	fp = fopen(file_name, "r");
	if(fp == NULL)
		return 0;

	fscanf(fp, "%s %d %d %d %d %d %d %d %d %d", 
		&enemy->name, &enemy->enemy_num, &enemy->if_boss, &enemy->HP, &enemy->attack,
		&enemy->defence, &enemy->a_masic, &enemy->d_masic, &enemy->speed, &enemy->ability);
	fclose(fp);

	return 1;
}

//全てのベースとなる敵の初期化
int InitEnemies(void)
{
	if(InitEnemy(&pawn, "Pawn_Status_Info.txt") == 0)
		return 0;
	if(InitEnemy(&knight, "Knight_Status_Info.txt") == 0)
		return 0;
	if(InitEnemy(&bishop, "Bishop_Status_Info.txt") == 0)
		return 0;
	if(InitEnemy(&rook, "Rook_Status_Info.txt") == 0)
		return 0;
	if(InitEnemy(&queen, "Queen_Status_Info.txt") == 0)
		return 0;
	if(InitEnemy(&king, "King_Status_Info.txt") == 0)
		return 0;

	return 1;
}


/*アビリティー*/

//アビリティー情報構造体
typedef struct{
	char name[20];
	unsigned short ability_num;
	unsigned short attack;
	unsigned short speed;
}Ability;

/*グローバル変数の宣言*/
Ability SC;
Ability F;
Ability BRS;
Ability HF;
Ability AO;

//各アビリティーを初期化
int InitAbility(Ability *ability, char *file_name)
{
	FILE *fp;

	fp = fopen(file_name, "r");
	if(fp == NULL)
		return 0;

	fscanf(fp, "%s %d %d %d", 
		&ability->name, &ability->ability_num, &ability->attack, &ability->speed);
	fclose(fp);

	return 1;
}

//全てのアビリティーの初期化
int InitAbilities(void)
{
	if(InitAbility(&SC, "SwordCut.txt") == 0)
		return 0;
	if(InitAbility(&F, "Flame.txt") == 0)
		return 0;
	if(InitAbility(&BRS, "BigRevolveSword.txt") == 0)
		return 0;
	if(InitAbility(&HF, "HellFlame.txt") == 0)
		return 0;
	if(InitAbility(&AO, "AbsoluteObedience.txt") == 0)
		return 0;

	return 1;
}


/*アイテム*/

//数値にアイテムの名前を与え、ラベルとして利用する
enum {potion, str_att, str_def};

//ポーション関数
void GetPotionEffect(void)
{
	tmp_HP += hero.HP / 2;
	if(tmp_HP > hero.HP)
		tmp_HP = hero.HP;
}

//攻撃力強化関数
void GetSAEffect(void)
{
	switch(SA_counter) {
		case -1:
			tmp_SA = hero.attack;
			SA_counter = 7;
			break;
		case 0:
			hero.attack = tmp_SA;
			SA_counter = -1;
			return;
		case 7:
			hero.attack += (tmp_SA / 2);
			SA_counter--;
			break;
		default:
			SA_counter--;
	}
}

//防御力強化関数
void GetSDEffect(void)
{
	switch(SD_counter) {
		case -1:
			tmp_SD = hero.defence;
			SD_counter = 7;
			break;
		case 0:
			hero.defence = tmp_SD;
			SD_counter = -1;
			return;
		case 7:
			hero.defence += (tmp_SD / 2);
			SD_counter--;
			break;
		default:
			SD_counter--;
	}
}


/*アルゴリズム*/

//主人公から与えられる敵のダメージ計算
unsigned short GetEnemyDamage(Hero *H_GD, Enemy *E_GD, Ability *A_GD)
{
	int rand_val;
	unsigned short damage_val;
	rand_val = rand() % ((H_GD->level * 2 + 100) + 1);
	damage_val = (double)(H_GD->attack * A_GD->attack) / E_GD->defence + (double)H_GD->exp_value / ((E_GD->defence * E_GD->d_masic) - A_GD->speed) + (int)(((double)(rand_val) / (H_GD->level * 2 + 100)) * 10);

	return damage_val;
}

//敵から与えられる主人公のダメージ計算
unsigned short GetHeroDamage(Hero *H_GD, Enemy *E_GD, Ability *A_GD)
{
	int rand_val;
	unsigned short damage_val;
	rand_val = rand() % (((int)((H_GD->level * 2) / 3) * 2 + 100) + 1);
	damage_val = (double)(E_GD->attack * A_GD->attack) / H_GD->defence + (double)((H_GD->exp_value * 2) / 3) / ((H_GD->defence * H_GD->d_masic) - A_GD->speed) + (int)((double)(rand_val) / (((H_GD->level * 2) / 3) * 2 + 100) * 10);

	return damage_val;
}

//戦闘に勝つことによって得られる経験値
void GetExp(Hero *H_GE, Enemy *E_GE)
{
	int rand_val;
	unsigned short get_exp;
	rand_val = rand() % ((H_GE->level * 2 + 100) + 1);
	get_exp = E_GE->HP + E_GE->attack + E_GE->defence + E_GE->a_masic + E_GE->d_masic + E_GE->speed + (E_GE->HP + E_GE->attack + E_GE->defence + E_GE->a_masic + E_GE->d_masic + E_GE->speed) / 6 + (int)(((double)(rand_val) / (H_GE->level * 2 + 100)) * 10);
	get_exp *= 2;

	H_GE->exp_value += get_exp;
}

//１つレベルアップするのに必要な経験値
void GetLvUpExp(Hero *GLUE)
{
	unsigned short lvup_exp;
	lvup_exp = (GLUE->HP + GLUE->attack + GLUE->defence + GLUE->a_masic + GLUE->d_masic + GLUE->speed) * GLUE->level;
	if(lvup_exp >= 10 && lvup_exp < 100) {
		if(lvup_exp % 10 >= 5) {
			int tmp;
			tmp = lvup_exp % 10;
			tmp = 10 - tmp;
			lvup_exp += tmp;
		}
		if(lvup_exp % 10 < 5) {
			int tmp;
			tmp = lvup_exp % 10;
			lvup_exp -= tmp;
		}
	}
	if(lvup_exp >= 100) {
		if(lvup_exp % 100 >= 50) {
			int tmp;
			tmp = lvup_exp % 100;
			tmp = 100 - tmp;
			lvup_exp += tmp;
		}
		if(lvup_exp % 100 < 50) {
			int tmp;
			tmp = lvup_exp % 100;
			lvup_exp -= tmp;
		}
	}

	GLUE->lvup_exp = lvup_exp;
}

//レベルアップによるステータスの上昇
void GetBasicStatusUpValue(Hero *GBSUV)
{
	int rand_val;
	unsigned short lvexp;
	short Bsuv;

	lvexp = GBSUV->exp_value / GBSUV->level;


	rand_val = rand() % 5;
	rand_val = rand_val - 2;
	Bsuv = (lvexp * 5) / 100 + rand_val;
	if(Bsuv < 0)
		Bsuv = 0;
	GBSUV->HP += Bsuv;

	rand_val = rand() % 5;
	rand_val = rand_val - 2;
	Bsuv = (lvexp * 2) / 100 + rand_val;
	if(Bsuv < 0)
		Bsuv = 0;
	GBSUV->attack += Bsuv;

	rand_val = rand() % 5;
	rand_val = rand_val - 2;
	Bsuv = (lvexp * 2) / 100 + rand_val;
	if(Bsuv < 0)
		Bsuv = 0;
	GBSUV->defence += Bsuv;

	rand_val = rand() % 5;
	rand_val = rand_val - 2;
	Bsuv = (lvexp * 2) / 100 + rand_val;
	if(Bsuv < 0)
		Bsuv = 0;
	GBSUV->a_masic += Bsuv;

	rand_val = rand() % 5;
	rand_val = rand_val - 2;
	Bsuv = (lvexp * 2) / 100 + rand_val;
	if(Bsuv < 0)
		Bsuv = 0;
	GBSUV->d_masic += Bsuv;

	rand_val = rand() % 5;
	rand_val = rand_val - 2;
	Bsuv = (lvexp * 2) / 100 + rand_val;
	if(Bsuv < 0)
		Bsuv = 0;
	GBSUV->speed += Bsuv;
}