// ギルド基本データ変更要求
int mapif_parse_GuildBasicInfoChange(int fd, int guild_id, int type, const char *data, int len) {
	struct guild *g;
	short dw = *((short *)data);

	g = idb_get(guild_db, guild_id);
	if (g == NULL)
		return 0;

	switch(type) {
	case GBI_GUILDLV:
		if (dw > 0 && g->guild_lv + dw <= 50) {
			g->guild_lv+=dw;
			g->skill_point+=dw;
		} else if (dw < 0 && g->guild_lv + dw >= 1)
			g->guild_lv += dw;
		mapif_guild_info(-1, g);
		return 0;
	default:
		ShowError("int_guild: GuildBasicInfoChange: Unknown type %d\n", type);
		break;
	}
	mapif_guild_basicinfochanged(guild_id, type, data, len);

	return 0;
}
// ギルドの情報の再計算
int guild_calcinfo(struct guild *g)
{
	int i, c;
	unsigned int nextexp;
	struct guild before = *g;

	// スキルIDの設定
	for(i = 0; i < MAX_GUILDSKILL; i++)
		g->skill[i].id=i+GD_SKILLBASE;

	// ギルドレベル
	if (g->guild_lv <= 0)
		g->guild_lv = 1;
	nextexp = guild_nextexp(g->guild_lv);
	if (nextexp > 0) {
		while(g->exp >= nextexp && nextexp > 0) {	//fixed guild exp overflow [Kevin]
			g->exp -= nextexp;
			g->guild_lv++;
			g->skill_point++;
			nextexp = guild_nextexp(g->guild_lv);
		}
	}

	// ギルドの次の経験値
	g->next_exp = guild_nextexp(g->guild_lv);

	// メンバ上限(ギルド拡張適用)
	g->max_member = 16 + guild_checkskill(g, GD_EXTENSION) * 6; //Guild Extention skill - currently adds 6 to max per skill lv.
	if(g->max_member > MAX_GUILD)
	{	
		ShowError("Guild %d:%s has capacity for too many guild members (%d), max supported is %d\n", g->guild_id, g->name, g->max_member, MAX_GUILD);
		g->max_member = MAX_GUILD;
	}

	// 平均レベルとオンライン人数
	g->average_lv = 0;
	g->connect_member = 0;
	c = 0;
	for(i = 0; i < g->max_member; i++) {
		if (g->member[i].account_id > 0) {
			g->average_lv += g->member[i].lv;
			c++;
			if (g->member[i].online > 0)
				g->connect_member++;
		}
	}
	if(c) g->average_lv /= c;

	// 全デ??を送る必要がありそう
	if (g->max_member != before.max_member ||
		g->guild_lv != before.guild_lv ||
		g->skill_point != before.skill_point) {
		mapif_guild_info(-1, g);
		return 1;
	}

	return 0;
}
// ギルド情報要求
int mapif_parse_GuildInfo(int fd, int guild_id) {
	struct guild *g;

	g = idb_get(guild_db, guild_id);
	if (g != NULL){
		guild_calcinfo(g);
		mapif_guild_info(fd, g);
	} else
		mapif_guild_noinfo(fd, guild_id);

	return 0;
}
// ギルドスキルアップ要求
int mapif_parse_GuildSkillUp(int fd, int guild_id, int skill_num, int account_id) {
	struct guild *g = idb_get(guild_db, guild_id);
	int idx = skill_num - GD_SKILLBASE;

	if (g == NULL || idx < 0 || idx >= MAX_GUILDSKILL)
		return 0;

	if (g->skill_point > 0 && g->skill[idx].id > 0 && g->skill[idx].lv < 10) {
		g->skill[idx].lv++;
		g->skill_point--;
		if (guild_calcinfo(g) == 0)
			mapif_guild_info(-1, g);
		mapif_guild_skillupack(guild_id, skill_num, account_id);
	}

	return 0;
}
// Delete member from guild
int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes)
{
	int i, j;

	struct guild* g = (struct guild*)idb_get(guild_db, guild_id);
	if( g == NULL )
	{
		//TODO
		return 0;
	}

	// Find the member
	ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id );
	if( i == g->max_member )
	{
		//TODO
		return 0;
	}

	if( flag )
	{	// 追放の場合追放リストに入れる
		ARR_FIND( 0, MAX_GUILDEXPULSION, j, g->expulsion[j].account_id == 0 );
		if (j == MAX_GUILDEXPULSION)
		{	// 一杯なので古いのを消す
			for(j = 0; j < MAX_GUILDEXPULSION - 1; j++)
				g->expulsion[j] = g->expulsion[j+1];
			j = MAX_GUILDEXPULSION - 1;
		}
		// Save the expulsion entry
		g->expulsion[j].account_id = account_id;
		safestrncpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH);
		safestrncpy(g->expulsion[j].mes, mes, 40);
	}

	mapif_guild_withdraw(guild_id, account_id, char_id, flag, g->member[i].name, mes);

	memset(&g->member[i], 0, sizeof(struct guild_member));

	if (guild_check_empty(g) == 0)
		mapif_guild_info(-1,g);// まだ人がいるのでデ??送信

	return 0;
}
// ギルド脱退/追放要求
int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes) {
	struct guild *g = NULL;
	int i, j;

	g = idb_get(guild_db, guild_id);
	if (g != NULL) {
		for(i = 0; i < MAX_GUILD; i++) {
			if (g->member[i].account_id == account_id && g->member[i].char_id == char_id) {
//				printf("%d %d\n", i, (int)(&g->member[i]));
//				printf("%d %s\n", i, g->member[i].name);

				if (flag) {	// 追放の場合追放リストに入れる
					for(j = 0; j < MAX_GUILDEXPULSION; j++) {
						if (g->expulsion[j].account_id == 0)
							break;
					}
					if (j == MAX_GUILDEXPULSION) {	// 一杯なので古いのを消す
						for(j = 0; j < MAX_GUILDEXPULSION - 1; j++)
							g->expulsion[j] = g->expulsion[j+1];
						j = MAX_GUILDEXPULSION - 1;
					}
					g->expulsion[j].account_id = account_id;
					memcpy(g->expulsion[j].acc, "dummy", NAME_LENGTH-1);
					memcpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH-1);
					memcpy(g->expulsion[j].mes, mes, 40);
				}

				mapif_guild_leaved(guild_id, account_id, char_id, flag, g->member[i].name, mes);
//				printf("%d %d\n", i, (int)(&g->member[i]));
//				printf("%d %s\n", i, (&g->member[i])->name);
				memset(&g->member[i], 0, sizeof(struct guild_member));

				if (guild_check_empty(g) == 0)
					mapif_guild_info(-1,g);// まだ人がいるのでデータ送信

				return 0;
			}
		}
	}
	return 0;
}
// ギルドメンバ追加要求
int mapif_parse_GuildAddMember(int fd, int guild_id, struct guild_member *m) {
	struct guild *g;
	int i;

	g = idb_get(guild_db, guild_id);
	if (g == NULL) {
		mapif_guild_memberadded(fd, guild_id, m->account_id, m->char_id, 1);
		return 0;
	}

	for(i = 0; i < g->max_member; i++) {
		if (g->member[i].account_id == 0) {
			memcpy(&g->member[i], m, sizeof(struct guild_member));
			mapif_guild_memberadded(fd, guild_id, m->account_id, m->char_id, 0);
			guild_calcinfo(g);
			mapif_guild_info(-1, g);

			return 0;
		}
	}
	mapif_guild_memberadded(fd, guild_id, m->account_id, m->char_id, 1);

	return 0;
}
// ギルドメンバ追加要求
int mapif_parse_GuildAddMember(int fd, int guild_id, struct guild_member *m)
{
	struct guild *g;
	int i;

	g = (struct guild*)idb_get(guild_db, guild_id);
	if (g == NULL) {
		mapif_guild_memberadded(fd, guild_id, m->account_id, m->char_id, 1);
		return 0;
	}

	ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 );
	if( i < g->max_member )
	{
		memcpy(&g->member[i], m, sizeof(struct guild_member));
		mapif_guild_memberadded(fd, guild_id, m->account_id, m->char_id, 0);
		guild_calcinfo(g);
		mapif_guild_info(-1, g);
	}
	else
		mapif_guild_memberadded(fd, guild_id, m->account_id, m->char_id, 1);

	return 0;
}
// ギルド作成要求
int mapif_parse_CreateGuild(int fd, int account_id, char *name, struct guild_member *master) {
	struct guild *g;
	int i;

	for(i = 0; i < NAME_LENGTH && name[i]; i++) {
		if (!(name[i] & 0xe0) || name[i] == 0x7f) {
			ShowInfo("Create Guild: illegal guild name [%s]\n", name);
			mapif_guild_created(fd, account_id, NULL);
			return 0;
		}
	}

	if ((g = search_guildname(name)) != NULL) {
		ShowInfo("Create Guild: same name guild exists [%s]\n", name);
		mapif_guild_created(fd, account_id, NULL);
		return 0;
	}

	// Check Authorised letters/symbols in the name of the character
	if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
		for (i = 0; i < NAME_LENGTH && name[i]; i++)
			if (strchr(char_name_letters, name[i]) == NULL) {
				mapif_guild_created(fd,account_id,NULL);
				return 0;
			}
	} else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
		for (i = 0; i < NAME_LENGTH && name[i]; i++)
			if (strchr(char_name_letters, name[i]) != NULL) {
				mapif_guild_created(fd,account_id,NULL);
				return 0;
			}
	}

	g = (struct guild *) aCalloc(sizeof(struct guild), 1);
	if (g == NULL) {
		ShowFatalError("int_guild: CreateGuild: out of memory !\n");
		mapif_guild_created(fd, account_id, NULL);
		exit(0);
	}
//	memset(g, 0, sizeof(struct guild)); Meh...
	g->guild_id = guild_newid++;
	memcpy(g->name, name, NAME_LENGTH-1);
	memcpy(g->master, master->name, NAME_LENGTH-1);
	memcpy(&g->member[0], master, sizeof(struct guild_member));

	g->position[0].mode = 0x11;
	strcpy(g->position[                  0].name, "GuildMaster");
	strcpy(g->position[MAX_GUILDPOSITION-1].name, "Newbie");
	for(i = 1; i < MAX_GUILDPOSITION-1; i++)
		sprintf(g->position[i].name, "Position %d", i + 1);

	// ここでギルド情報計算が必要と思われる
	g->max_member = 16;
	g->average_lv = master->lv;
	for(i = 0; i < MAX_GUILDSKILL; i++)
		g->skill[i].id=i + GD_SKILLBASE;

	idb_put(guild_db, g->guild_id, g);

	mapif_guild_created(fd, account_id, g);
	mapif_guild_info(fd, g);

	if(log_inter)
		inter_log("guild %s (id=%d) created by master %s (id=%d)" RETCODE,
			name, g->guild_id, master->name, master->account_id);

	return 0;
}