/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

	FILE	: Skill.cpp

+ ------ Explanation of file --------------------------------------------------------------------------

	ADSはテキスト自動解析で半自動に効果スクリプトを組むらしい
	アンジュは効果文固定だからできないこともない

+ _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

#include "Common.h"

#include "CardData.h"
#include "Phase.h"
#include "Field.h"
#include "Mouse.h"
#include "Dialog.h"

#include "Skill.h"

// 関数名&関数リスト
SKILL_NAME gSkillName[] = {
	// SkillTiming
	{"stLinkStepStart",		&Skill::stLinkStepStart},
	{"stPlayActionZone",	&Skill::stPlayActionZone},
	{"stPlay",				&Skill::stPlay},
	{"stAlways",			&Skill::stAlways},
	{"stStartup",			&Skill::stStartup},
	// SkillCost
	{"scFall",				&Skill::scFall},
	{"scFallNum",			&Skill::scFallNum},
	{"scDumpHand",			&Skill::scDumpHand},
	// SkillIf
	{"siLink",				&Skill::siLink},
	{"siColorNum",			&Skill::siColorNum},
	{"siUseNum",			&Skill::siUseNum},
	{"siEnergyFallAll",		&Skill::siEnergyFallAll},
	// SkillEffect
	// B1
	{"seDraw",				&Skill::seDraw},
	{"seShuffle",			&Skill::seShuffle},
	{"seAwake",				&Skill::seAwake},
	{"seAwakeEnergy",		&Skill::seAwakeEnergy},
	{"seDamage",			&Skill::seDamage},
	{"seDumpHand",			&Skill::seDumpHand},
	{"seDumpHandOp",		&Skill::seDumpHandOp},
	{"seDumpDeck",			&Skill::seDumpDeck},
	{"seDumpDamage",		&Skill::seDumpDamage},
	{"seSearchDeckPrg",		&Skill::seSearchDeckPrg},
	{"seSearchDisCardPrg",	&Skill::seSearchDisCardPrg},
	{"seAddEnergy",			&Skill::seAddEnergy},
	{"sePutDisCardPrg",		&Skill::sePutDisCardPrg},
	{"sePowerUp",			&Skill::sePowerUp},
	{"sePowerUpAll",		&Skill::sePowerUpAll},
	{"sePowerUpNum",		&Skill::sePowerUpNum},
	{"sePowerUpHand",		&Skill::sePowerUpHand},
	{"sePowerUpEnergy",		&Skill::sePowerUpEnergy},
	{"seStrikeUp",			&Skill::seStrikeUp},
	{"seBouncePrg",			&Skill::seBouncePrg},
	{"seBouncePrgDeck",		&Skill::seBouncePrgDeck},
	{"seRemovePrg",			&Skill::seRemovePrg},
	{"seChangeHandDamage",	&Skill::seChangeHandDamage},
	{"seDamageFront",		&Skill::seDamageFront},
	{"seDeckTopMoveTorD",	&Skill::seDeckTopMoveTorD},
};

#define ARGINT(n, d)	((n) < (*m_pFuncList)[m_state]->argInt.size() ? (*m_pFuncList)[m_state]->argInt[(n)] : (d))
#define ARGSTR(n, d)	((n) < (*m_pFuncList)[m_state]->argStr.size() ? (*m_pFuncList)[m_state]->argStr[(n)].c_str() : (d))
#define COSTERROR		{printf("コストが支払えません\n"); return(SKILL_RET_END);}

Skill::Skill()
{
	m_state = 0;
	m_sState = 0;
	m_skillNum = -1;
	m_pFuncList = NULL;
}

Skill::~Skill()
{
	release();
}

void Skill::init(Phase* pPhase, Field* pField, Dialog* pDlg)
{
	m_pPhase = pPhase;
	m_pField = pField;
	m_pDialog = pDlg;

	readBinary();
}

//! 発動
int Skill::invoke(Card* card, int skillNo, int code)
{
	m_ret = -1;
	// 発動スキルの検索
	if(m_skillNum == -1){
		if(searchSkill(card, skillNo)){
			// 初期化
			m_state = 0;
			m_sState = 0;
			m_linkNum = 0;
			m_invokeNum = 0;
			m_pPhase->m_canOpenDlg = false;
if(code==SKILL_CODE_INVOKE)printf("効果発動します\n");
		}
	}

	if(m_skillNum != -1){
		// 関数リストセット
		if(!m_pFuncList){
			switch(code){
				case SKILL_CODE_INVOKE:
					m_pFuncList = &m_scriptList[m_skillNum]->skill;
					break;
				case SKILL_CODE_CHECK_TIMING:
					m_pFuncList = &m_scriptList[m_skillNum]->chkTmg;
					break;
				case SKILL_CODE_CHECK_COST:
					m_pFuncList = &m_scriptList[m_skillNum]->chkCst;
					break;
			}
		}

		// 各カードの効果を呼ぶ
		if(!m_pFuncList->empty()){
			m_ret = (this->*gSkillName[(*m_pFuncList)[m_state]->fncNum].func)();
		}else{
			switch(code){
				case SKILL_CODE_INVOKE:			m_ret = SKILL_RET_END;	break;
				case SKILL_CODE_CHECK_TIMING:	m_ret = FALSE;			break;
				case SKILL_CODE_CHECK_COST:		m_ret = TRUE;			break;
			}
		}
		// チェックの場合はそのままリセット
		if(code == SKILL_CODE_CHECK_COST || code == SKILL_CODE_CHECK_TIMING){
			m_skillNum = -1;
			m_pPhase->m_canOpenDlg = true;
			m_pFuncList = NULL;
		}else if(m_ret == SKILL_RET_END){
			m_invokeNum++;
			if(m_pFuncList && m_state >= (int)m_pFuncList->size() && m_invokeNum < m_linkNum){
				// 発動回数が残っているので初期化して再度発動
				m_state = 0;
				m_sState = 0;
				m_card[0]->m_useSkill[skillNo]++;
				m_ret = SKILL_RET_INVOKE;
			}else{
printf("[効果]終了しました\n");
				clear(code, skillNo);
			}
		}
	}

	return(m_ret);
}
//! 発動スキル検索
bool Skill::searchSkill(Card* card, int skillNo)
{
	bool bRet = false;

	const char*	serStr = SNtSS(HIWORD(card->m_ci.cardNo));
	int			serNum = LOWORD(card->m_ci.cardNo);

	// 一致するスクリプトを検索
	for(iteScript ite = m_scriptList.begin(); ite != m_scriptList.end(); ite++){
		if(	(strcmp((*ite)->serStr.c_str(), serStr) == 0) &&
			(serNum == (*ite)->serNum) && (skillNo == (*ite)->sklNum))
		{
			int num = distance(m_scriptList.begin(), ite);
			if(m_scriptList[num]->skill.size() > 0){
				// 対象カード記憶
				m_card[0] = card;
				m_skillNum = num;
				bRet = true;
				break;
			}
		}
	}

	return(bRet);
}
//! 発動タイミング一致スキル検索
int Skill::searchTinimg(Card* card, int timing)
{
	int iRet = -1;
	
	for(int i = 0; i < SKILL_MAX; i++){
		if(invoke(card, i, SKILL_CODE_CHECK_TIMING) == timing){
			iRet = i;
			break;
		}
	}

	return(iRet);
}

//! 解放
void Skill::release(void)
{
	for(iteScript iScr = m_scriptList.begin(); iScr != m_scriptList.end(); iScr++){
		vecFunc* vFunc[SKILLTYPE_MAX] = {&(*iScr)->chkTmg, &(*iScr)->chkCst, &(*iScr)->skill};
		for(int i = 0; i < SKILLTYPE_MAX; i++){
			for(iteFunc iFnc = vFunc[i]->begin(); iFnc != vFunc[i]->end(); iFnc++){
				delete(*iFnc);
			}
			vFunc[i]->clear();
		}
		delete(*iScr);
	}
}

//! バイナリ読み込み
void Skill::readBinary(void)
{
#define READNUM(num)		{memcpy_s(&num, sizeof(int), &scriptData[index], sizeof(int)); index += sizeof(int);}
#define READSTR(str)		{str = &scriptData[index]; index += strlen(&scriptData[index])+1;}
#define PUSHNUM(vNum)		{int n; READNUM(n); vNum.push_back(n);}
#define PUSHSTR(vStr)		{char* c; READSTR(c); vStr.push_back(c);}

	FILE*			fp;
	SCRIPT_DATA*	pScript;
	FUNC_DATA*		pFunc;
	char*			scriptData;
	int				fileStart;
	int				fileSize;
	int				index = 0;
	int				scriptNum;
	int				funcNum;
	int				argNum;

	fopen_s(&fp, "Data\\CardScript.dat", "rb");
	if(!fp){
		printf("error:CardScript.datが存在しません\n");
		return;
	}

	// サイズ取得
	fileStart = fseek(fp, 0, SEEK_END);
	fileSize = ftell(fp);
	fseek(fp, fileStart, SEEK_SET);

	// バッファに読み込み
	scriptData = (char*)malloc(fileSize);
	fread_s(scriptData, fileSize, fileSize, 1, fp);
	fclose(fp);

	// バッファから分解
	READNUM(scriptNum);		// スクリプト数
	for(int scr = 0; scr < scriptNum; scr++){
		m_scriptList.push_back(new SCRIPT_DATA());
		pScript = m_scriptList.back();

		READSTR(pScript->serStr);	// シリーズ名
		READNUM(pScript->serNum);	// シリーズ番号
		READNUM(pScript->sklNum);	// スキル番号

		// タイミング, コスト, 効果関数
		vecFunc* vFunc[SKILLTYPE_MAX] = {&pScript->chkTmg, &pScript->chkCst, &pScript->skill};
		for(int fnc = 0; fnc < SKILLTYPE_MAX; fnc++){
			READNUM(funcNum);	// 各種数

			for(int i = 0; i < funcNum; i++){
				vFunc[fnc]->push_back(new FUNC_DATA());
				pFunc = vFunc[fnc]->back();

				READSTR(pFunc->name);		// 関数名

//				READNUM(argNum);			// タイプ数
//				for(int j = 0; j < argNum; j++){
//					PUSHNUM(pFunc->argTyp);	// タイプ
//				}

				READNUM(argNum);			// 数値引数数
				for(int j = 0; j < argNum; j++){
					PUSHNUM(pFunc->argInt);	// 数値引数
				}

				READNUM(argNum);			// 文字引数数
				for(int j = 0; j < argNum; j++){
					PUSHSTR(pFunc->argStr);	// 文字引数
				}

				// 関数名to関数番号
				int size = SIZEARY(gSkillName);
				for(int j = 0; j < size; j++){
					if(strcmp(pFunc->name.c_str(), gSkillName[j].name)==0){
						pFunc->fncNum = j;
						break;
					}
				}
			}
		}
	}

	free(scriptData);
#undef READNUM
#undef READSTR
#undef PUSHNUM
#undef PUSHSTR
}

//! 効果終了
void Skill::clear(int code, int skillNo)
{
	m_pField->selLockAll(SELECT_NON);

	// 使用回数加算
	m_card[0]->m_useSkill[skillNo-1]++;

	// カード解放
	for(int i = 0; i < 10; i++){
		m_card[i] = NULL;
	}
	m_state = 0;
	m_sState = 0;
	m_skillNum = -1;
	m_pFuncList = NULL;
	m_pPhase->m_canOpenDlg = true;
	m_pPhase->m_selectNum = 1;
}

//! 次ステートへ
void Skill::nextState(int state)
{
	m_pDialog->close();
	m_state += state;
	m_sState = 0;
	// 効果が残っていなければ終了
	if(m_state >= (int)m_pFuncList->size()){
		m_ret = SKILL_RET_END;
	}
}

//! --- SkillTiming ---
//! リンクステップ開始時
int Skill::stLinkStepStart(void)
{
	return(SKILL_TIMING_LINK_FIRST);
}
//! アクションゾーンに置かれた時
int Skill::stPlayActionZone(void)
{
	return(SKILL_TIMING_ACTION_FIRST);
}
//! 登場した時
int Skill::stPlay(void)
{
	return(SKILL_TIMING_PLAY_FIRST);
}
//! 常在効果
int Skill::stAlways(void)
{
	return(SKILL_TIMING_ALWAYS);
}
//! 起動効果
int Skill::stStartup(void)
{
	return(SKILL_TIMING_STARTUP);
}

//! --- SkillCost ---
//! 自身をフォール
int Skill::scFall(void)
{
	int isMust	= ARGINT(0, -1);	// 必ず払う
	int	isCheck	= ARGINT(1, -1);	// コストチェック

	if(isCheck){
		return(!isMust || m_card[0]->m_awake != CARD_FALL);
	}

	switch(m_sState){
		case 0:
			if(isMust){
				m_sState = 2;
			}else{
				m_pPhase->m_canOpenDlg = true;
				m_pDialog->open(DLG_T_YESNO, DLG_PLACE_CENTER, NULL, "コストを払いますか？");
				m_pPhase->m_canOpenDlg = false;
				m_sState++;
			}
			break;
		case 1:
			if(LOWORD(m_pDialog->getResult()) == BTN_ID_YES){
				m_pDialog->close();
				m_sState++;
			}else if(LOWORD(m_pDialog->getResult()) == BTN_ID_NO){
				m_pDialog->close();
				nextState(99);
			}
			break;
		case 2:
			if(m_card[0]->m_awake != CARD_FALL){
				m_pField->fallProgress(PLY_MY, m_card[0]->m_num);
				nextState();
printf("[コスト]%sをフォールしました\n", m_card[0]->m_ci.name);
			}else{
				COSTERROR;
			}
			break;
	}
	
	return(m_ret);
}
//! n枚をフォール
int Skill::scFallNum(void)
{
	int	num		= ARGINT(0, -1);	// フォール枚数
	int	isMy	= ARGINT(1, -1);	// 自身も対象か
	int isMust	= ARGINT(2, -1);	// 必ず払う
	int	isCheck	= ARGINT(3, -1);	// コストチェック

	// 対象チェック
	int my = 0;
	if(isMy && m_card[0]->m_ci.type == TYPE_PG){
		if(m_card[0]->m_awake != CARD_AWAKE){
			my = 1;
		}
	}

	// コストチェック
	if(isCheck){
		return(!isMust || m_pField->getValueNum(PLY_MY, ZONE_PROGRESS, CD_AWAKE, CARD_AWAKE) - my >= num);
	}

	switch(m_sState){
		case 0:
			if(isMust){
				m_sState = 2;
			}else{
				m_pPhase->m_canOpenDlg = true;
				m_pDialog->open(DLG_T_YESNO, DLG_PLACE_CENTER, NULL, "コストを払いますか？");
				m_pPhase->m_canOpenDlg = false;
				m_sState++;
			}
			break;
		case 1:
			if(LOWORD(m_pDialog->getResult()) == BTN_ID_YES){
				m_pDialog->close();
				m_sState++;
			}else if(LOWORD(m_pDialog->getResult()) == BTN_ID_NO){
				m_pDialog->close();
				nextState(99);
			}
			break;
		case 2:
			if(m_pField->getValueNum(PLY_MY, ZONE_PROGRESS, CD_AWAKE, CARD_AWAKE) - my < num){
				COSTERROR;
			}else{
				m_pField->selLockValueExcept(PLY_MY, ZONE_PROGRESS, CD_AWAKE, CARD_AWAKE);
				if(!isMy && m_card[0]->m_ci.type == TYPE_PG){
					m_pField->selLockOnce(PLY_MY, ZONE_PROGRESS, m_card[0]->m_num);
				}
				m_pPhase->m_selectNum = num;
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "[コスト]フォールするプログレスを\n%d枚選択して下さい", num);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_SEEMY, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}
			break;
		case 3:
			if(m_pField->getSelectNum() == num){
				for(int i = 0; i < num; i++){
					m_pField->fallProgress(PLY_MY, m_pField->getSelect(i)->m_num);
printf("[コスト]%sをフォールしました\n", m_pField->getSelect(i)->m_ci.name);
				}
				nextState();
			}
			break;
	}

	return(m_ret);
}
//! 手札を捨てる
int Skill::scDumpHand(void)
{
	int	num		= ARGINT(0, -1);	// 捨てる枚数
	int isMust	= ARGINT(1, -1);	// 必ず払う
	int	isCheck	= ARGINT(2, -1);	// コストチェック

	if(isCheck){
		return(!isMust || m_pField->getHandNum(PLY_MY) >= num);
	}

	switch(m_sState){
		case 0:
			if(isMust){
				m_sState = 2;
			}else{
				m_pPhase->m_canOpenDlg = true;
				m_pDialog->open(DLG_T_YESNO, DLG_PLACE_CENTER, NULL, "コストを払いますか？");
				m_pPhase->m_canOpenDlg = false;
				m_sState++;
			}
			break;
		case 1:
			if(LOWORD(m_pDialog->getResult()) == BTN_ID_YES){
				m_pDialog->close();
				m_sState++;
			}else if(LOWORD(m_pDialog->getResult()) == BTN_ID_NO){
				m_pDialog->close();
				nextState(99);
			}
			break;
		case 2:{
			if(m_pField->getHandNum(PLY_MY) < num){
				COSTERROR;
			}
			m_pField->selLockZoneExcept(PLY_MY, ZONE_HAND);
			m_pPhase->m_selectNum = num;
			m_sState++;

			m_pPhase->m_canOpenDlg = true;
			char text[256] = {};
			wsprintf(text, "[コスト]捨てる手札を%d枚選択して下さい", num);
			m_pDialog->open(DLG_TEXT, DLG_PLACE_CENTER, NULL, text);
			m_pPhase->m_canOpenDlg = false;
			break;
		}
		case 3:
			if(m_pField->getSelectNum() == num){
				while(m_pField->getSelectNum() > 0){
printf("[コスト]%sを捨札に置きました\n", m_pField->getSelect()->m_ci.name);
					m_pField->dumpHand(PLY_MY, m_pField->getSelect()->m_num);
				}
				nextState();
			}
			break;
	}

	return(m_ret);
}

//! --- SkillIf ---
//! リンク
int Skill::siLink(void)
{
	enum {
		REST_ANY,	REST_SGM,	REST_OMG,	// リンク成功までの残りフレーム数
		TEMP_ALL,	TEMP_SGM,	TEMP_OMG,	// 処理場の残りフレーム数
		DAM_REV,							// ダメージリバースフラグ
	};
	int	link	= ARGINT(0, -1);	// リンク数
	int	any		= ARGINT(1, -1);	// 任意アイコン数
	int	sigma	= ARGINT(2, -1);	// シグマ数
	int	omega	= ARGINT(3, -1);	// オメガ数
	int next	= ARGINT(4, 99);	// 条件スキップ数

	// temp[0~2] : 各種リンク計算残り数
	// temp[3~5] : 処理場フレーム数
	// temp[6]	 : ダメージリバース

	switch(m_sState){
		// ドロー
		case 0:
			// 複数回リンク
			if(m_linkNum > 0){
				nextState();
			}else{
if(m_pField->getDeckNum(PLY_MY)>0){
switch(m_pField->getDeck(PLY_MY, m_pField->getDeckNum(PLY_MY)-1)->m_ci.frame){
case FRAME_NON:  printf("フレーム：   ");break;
case FRAME_SIGMA:printf("フレーム：Σ ");break;
case FRAME_OMEGA:printf("フレーム：Ω ");break;
case FRAME_ALL:  printf("フレーム：∀ ");break;
}printf("(%s)\n", m_pField->getDeck(PLY_MY, m_pField->getDeckNum(PLY_MY)-1)->m_ci.name);
}
				if(m_pPhase->checkDraw(link + m_card[0]->getAddLink(), m_pField->addTemp(PLY_MY))){
					m_pField->wait();
					m_temp[DAM_REV] = 0;
					m_sState++;
				}
			}
			break;

		// リンク計算
		case 1:
			m_linkNum = 0;
			ZeroMemory(m_temp, sizeof(int)*(TEMP_OMG+1));
			// 処理場のフレーム数
			for(int i = 0; i < m_pField->getTempNum(PLY_MY); i++){
				switch(m_pField->getTemp(PLY_MY, i)->m_ci.frame){
					case FRAME_SIGMA:	m_temp[TEMP_SGM]++;		break;
					case FRAME_OMEGA:	m_temp[TEMP_OMG]++;		break;
					case FRAME_ALL	:	m_temp[TEMP_ALL] += 2;	break;	// ∀は2個分になる
				}
			}
			// ダメージリバースはオールとして扱う
			m_temp[TEMP_ALL] += m_temp[DAM_REV];

			while(1){
				// tempに保存
				m_temp[REST_ANY] = any;
				m_temp[REST_SGM] = sigma;
				m_temp[REST_OMG] = omega;

				// ΣとΩの判定
				while(1){
					if((m_temp[TEMP_SGM] > 0) && (m_temp[REST_SGM] > 0)){
						m_temp[TEMP_SGM]--;
						m_temp[REST_SGM]--;
					}else if((m_temp[TEMP_OMG] > 0) && (m_temp[REST_OMG] > 0)){
						m_temp[TEMP_OMG]--;
						m_temp[REST_OMG]--;
					}else{
						break;
					}
				}

				// ANYの判定
				int nextLinkReq[FRAME_NUM] = {any, sigma, omega};	// 次に必要なリンク要求
				int restLinkReq[FRAME_NUM];							// 現時点で残っているリンク要求

				memcpy_s(restLinkReq, sizeof(restLinkReq), &m_temp[TEMP_ALL], sizeof(restLinkReq));

				// 次に必要な物を保護する
				while(1){
					if((restLinkReq[REST_SGM] > 0) && (nextLinkReq[REST_SGM] > 0)){
						restLinkReq[REST_SGM]--;
						nextLinkReq[REST_SGM]--;
					}else if((restLinkReq[REST_OMG] > 0) && (nextLinkReq[REST_OMG] > 0)){
						restLinkReq[REST_OMG]--;
						nextLinkReq[REST_OMG]--;
					}else{
						break;
					}
				}

				while(1){
					// 保護対象外を使用してANYを判定
					if((restLinkReq[REST_SGM] > 0) && (m_temp[REST_ANY] > 0)){
						restLinkReq[REST_SGM]--;
						m_temp[TEMP_SGM]--;
						m_temp[REST_ANY]--;
					}else if((restLinkReq[REST_OMG] > 0) && (m_temp[REST_ANY] > 0)){
						restLinkReq[REST_OMG]--;
						m_temp[TEMP_OMG]--;
						m_temp[REST_ANY]--;
					}else{
						// 保護対象外のみで終了できたか
						if(m_temp[REST_ANY] <= 0){
							break;
						}else{
							// できなかったので保護関係無しにANYを判定
							if(m_temp[TEMP_SGM] > 0){
								m_temp[TEMP_SGM]--;
								m_temp[REST_ANY]--;
							}else if(m_temp[TEMP_OMG] > 0){
								m_temp[TEMP_SGM]--;
								m_temp[REST_ANY]--;
							}else{
								break;
							}
						}
					}
				}

				// ∀の判定
				while(1){
					if(m_temp[TEMP_ALL] > 0){
						if(m_temp[REST_SGM] > 0){
							m_temp[TEMP_ALL]--;
							m_temp[REST_SGM]--;
						}else if(m_temp[REST_OMG] > 0){
							m_temp[TEMP_ALL]--;
							m_temp[REST_OMG]--;
						}else if(m_temp[REST_ANY] > 0){
							m_temp[TEMP_ALL]--;
							m_temp[REST_ANY]--;
						}else{
							break;
						}
					}else{
						break;
					}
				}

				// リンク成功
				if((m_temp[REST_SGM] <= 0) && (m_temp[REST_OMG] <= 0) && (m_temp[REST_ANY] <= 0)){
					m_linkNum++;

					// フレームがなくなっていれば終了
					if((m_temp[TEMP_ALL] <= 0) && (m_temp[TEMP_SGM] <= 0) && (m_temp[TEMP_OMG] <= 0)){
						m_sState++;
						break;
					}
				}else{
					m_sState++;
					break;
				}
			}
			break;

		// ダメージリバース確認
		case 2:{
			int isLink = -1;
// DEBUG
if(GetKeyState('1') < 0)m_linkNum = 1;
if(GetKeyState('2') < 0)m_linkNum = 2;
if(GetKeyState('3') < 0)m_linkNum = 3;
printf("%d回成功しています\n", m_linkNum);
printf("不足はANY%d, Σ%d, Ω%dです\n", m_temp[REST_ANY], m_temp[REST_SGM], m_temp[REST_OMG]);

			// ダメージリバース確認
			if(m_temp[DAM_REV] <= 0){
				int sel = m_pField->selLockValueExcept(PLY_MY, ZONE_DAMAGE, CD_REVERSE, CARD_FRONT);
				if(sel > 0){
					m_sState++;

					char text[100] = {};
					int tmp[3];
					if(m_temp[REST_ANY] + m_temp[REST_SGM] + m_temp[REST_OMG] > 0){
						tmp[0] = m_temp[REST_ANY];
						tmp[1] = m_temp[REST_SGM];
						tmp[2] = m_temp[REST_OMG];
					}else{
						tmp[0] = any;
						tmp[1] = sigma;
						tmp[2] = omega;
					}
					wsprintf(text, "%d回成功しています\nダメージリバースを使用しますか？\n不足 ANY:%d Σ:%d Ω:%d", m_linkNum, tmp[0], tmp[1], tmp[2]);
					m_pPhase->m_canOpenDlg = true;
					m_pDialog->open(DLG_T_YESNO, DLG_PLACE_TOP, m_card[0], text);
					m_pPhase->m_canOpenDlg = false;
				}else{
					if(m_linkNum > 0){
						isLink = TRUE;
					}else{
						isLink = FALSE;
					}
				}
			}else if(m_linkNum > 0){
				isLink = TRUE;
			}else{
				isLink = FALSE;
			}

			if(isLink != -1){
				if(isLink == TRUE){
					// リンク成功でストライク+1
					m_card[0]->m_addStrike.push_back(TURN_VALUE(1, TURN_NOW_BATTLE));
					nextState();
printf("リンク成功でストライク+1します\n");
				}else{
					nextState(next);
printf("リンク失敗しました\n");
				}
				// 処理場破棄
				int temp = m_pField->getTempNum(PLY_MY);
				// 見た目で右から
				for(int i = temp - 1; i >= 0 ; i--){
					m_pField->dumpTemp(PLY_MY, i);
				}
			}
			break;
		}
		// ダメージリバース確認
		case 3:{
			int ret = LOWORD(m_pDialog->getResult());
			if(ret == BTN_ID_YES){
				m_sState++;
				m_pDialog->close();
printf("裏返すダメージを1枚選択してください\n");
			}else if(ret == BTN_ID_NO){
				if(m_linkNum > 0){
					// リンク成功でストライク+1
					m_card[0]->m_addStrike.push_back(TURN_VALUE(1, TURN_NOW_BATTLE));
					nextState();
printf("リンク成功でストライク+1します\n");
				}else{
					nextState(next);
					m_pDialog->close();
printf("リンク失敗しました\n");
				}
				// 処理場破棄
				int temp = m_pField->getTempNum(PLY_MY);
				// 見た目で右から
				for(int i = temp - 1; i >= 0 ; i--){
					m_pField->dumpTemp(PLY_MY, i);
				}
			}
			break;
		}
		// ダメージリバース
		case 4:
			if(m_pField->getSelect()){
				m_pField->damageReverse(PLY_MY, m_pField->getSelect()->m_num);
				m_temp[DAM_REV] = 1;
				// 再判定
				m_sState = 1;
			}
			break;
	}

	return(m_ret);
}
//! 指定色n枚以上
int Skill::siColorNum(void)
{
	int	num		= ARGINT(0, -1);	// 条件枚数
	int	color	= ARGINT(1, -1);	// 条件色
	int next	= ARGINT(2, 99);	// 条件スキップ数

	if(m_pField->getValueNum(PLY_MY, ZONE_PROGRESS, CI_COLOR, color) >= num){
		nextState();
	}else{
switch(color){
case COL_BLUE:	printf("青が%d枚以上いません\n", num);break;
case COL_BLACK:	printf("黒が%d枚以上いません\n", num);break;
case COL_RED:	printf("赤が%d枚以上いません\n", num);break;
case COL_WHITE:	printf("白が%d枚以上いません\n", num);break;
case COL_GREEN:	printf("緑が%d枚以上いません\n", num);break;
}
		nextState(next);
	}

	return(m_ret);
}
//! n回まで
int Skill::siUseNum(void)
{
	int	skill	= ARGINT(0, -1);	// 発動スキル番号(sXX_YYY_Z : Z)
	int	num		= ARGINT(1, -1);	// 条件回数
	int next	= ARGINT(2, 99);	// 条件スキップ数

	if(m_card[0]->m_useSkill[skill-1] < num){
		nextState();
	}else{
printf("発動回数が%d回を超えています\n", num);
		nextState(next);
	}

	return(m_ret);
}
//! エナジーが全てフォール
int Skill::siEnergyFallAll(void)
{
	int next	= ARGINT(0, 99);	// 条件スキップ数

	if(m_pField->getAwakeEnergyNum(PLY_MY) <= 0){
		nextState();
	}else{
printf("エナジーが全てフォールされていません\n");
		nextState(next);
	}

	return(m_ret);
}

//! --- SkillEffect ---
//! ドローする
int Skill::seDraw(void)
{
	int	num	= ARGINT(0, -1);	// ドロー枚数

	if(m_pPhase->checkDraw(num, m_pField->drawCard(PLY_MY))){
		nextState();
printf("%d枚ドローしました\n", num);
	}

	return(m_ret);
}
//! シャッフルする
int Skill::seShuffle(void)
{
	int	isMy	= ARGINT(0, -1);	// 自分か

	if(isMy){
		m_pField->shuffleDeck(PLY_MY);
printf("デッキをシャッフルしました\n");
	}else{
		m_pField->shuffleDeck(PLY_OPPO);
printf("相手のデッキをシャッフルしました\n");
	}
	nextState();

	return(m_ret);
}
//! 自身をアウェイク
int Skill::seAwake(void)
{
	if(m_card[0]->m_awake == CARD_FALL){
		m_pField->awakeProgress(PLY_MY, m_card[0]->m_num);
		printf("%sをアウェイクしました\n", m_card[0]->m_ci.name);
	}else{
		printf("%sは既にアウェイクしています\n", m_card[0]->m_ci.name);
	}
	nextState();

	return(m_ret);
}
//! エナジーをアウェイク
int Skill::seAwakeEnergy(void)
{
	int	num	= ARGINT(0, -1);	// アウェイク枚数

	switch(m_sState){
		case 0:{
			m_pPhase->m_selectNum = MIN(m_pField->getFallEnergyNum(PLY_MY), num);
			if(m_pPhase->m_selectNum > 0){
				m_pField->selLockValueExcept(PLY_MY, ZONE_ENERGY, CD_AWAKE, CARD_FALL);
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "アウェイクするエナジーを%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_SEEMY, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}else{
				nextState();
printf("アウェイクするエナジーがありません\n");
			}
			break;
		}
		case 1:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
printf("debug:エナジー選択完了\n");
				for(int i = 0; i < m_pPhase->m_selectNum; i++){
printf("debug:アウェイク対象0x%x\n", m_pField->getSelect(i));
printf("%sをアウェイクしました\n", m_pField->getSelect(i)->m_ci.name);
					m_pField->awakeEnergy(PLY_MY, m_pField->getSelect(i)->m_num);
printf("debug:アウェイク完了%d枚目\n", i+1);
				}
				nextState();
			}
			break;
	}

	return(m_ret);
}
//! ダメージを与える
int Skill::seDamage(void)
{
	int	num	= ARGINT(0, -1);	// ダメージ数

	switch(m_sState){
		case 0:
			if(m_pPhase->checkDraw(num, m_pField->addTemp(PLY_OPPO))){
				m_sState++;
			}
			break;
		case 1:
			m_pField->giveDamage(PLY_OPPO, num);
			nextState();
			break;
	}

	return(m_ret);
}
//! 手札を捨てる
int Skill::seDumpHand(void)
{
	int	num	= ARGINT(0, -1);	// 捨てる枚数

	switch(m_sState){
		case 0:{
			m_pField->selLockZoneExcept(PLY_MY, ZONE_HAND);
			m_pPhase->m_selectNum = MIN(m_pField->getHandNum(PLY_MY), num);
			m_sState++;

			m_pPhase->m_canOpenDlg = true;
			char text[256] = {};
			wsprintf(text, "捨てる手札を%d枚選択して下さい", m_pPhase->m_selectNum);
			m_pDialog->open(DLG_TEXT, DLG_PLACE_CENTER, NULL, text);
			m_pPhase->m_canOpenDlg = false;
			break;
		}
		case 1:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				while(m_pField->getSelectNum() > 0){
printf("%sを捨札に置きました\n", m_pField->getSelect()->m_ci.name);
					m_pField->dumpHand(PLY_MY, m_pField->getSelect()->m_num);
				}
				nextState();
			}
			break;
	}

	return(m_ret);
}
//! 相手が手札を捨てる
int Skill::seDumpHandOp(void)
{
	int	num	= ARGINT(0, -1);	// 捨てる枚数

#if defined(_LOCAL_)
	switch(m_sState){
		case 0:
			if(m_pPhase->changePlayer()){
				m_sState++;
			}
			break;
		case 1:
			m_pPhase->m_selectNum = MIN(m_pField->getHandNum(PLY_MY), num);
			if(m_pPhase->m_selectNum > 0){
				m_pField->selLockZoneExcept(PLY_MY, ZONE_HAND);
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "捨てる手札を%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_CENTER, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}else{
printf("捨てる手札はありません\n");
				m_sState = 3;
			}
			break;
		case 2:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				while(m_pField->getSelectNum() > 0){
printf("%sを捨札に置きました\n", m_pField->getSelect()->m_ci.name);
					m_pField->dumpHand(PLY_MY, m_pField->getSelect()->m_num);
				}
				m_sState++;
			}
			break;
		case 3:
			if(m_pPhase->changePlayer()){
				nextState();
			}
			break;
	}
#elif defined(_NET_)
	nextState();
#endif

	return(m_ret);
}
//! デッキを捨てる
int Skill::seDumpDeck(void)
{
	int	num	= ARGINT(0, -1);	// 捨てる枚数

	if(m_pPhase->checkDraw(num, m_pField->dumpDeck(PLY_MY, m_pField->getDeckNum(PLY_MY)-1))){
		nextState();
printf("デッキを%d枚捨札に置きました\n", num);
	}

	return(m_ret);
}
//! ダメージを捨てる
int Skill::seDumpDamage(void)
{
	int	num	= ARGINT(0, -1);	// 捨てる枚数

	switch(m_sState){
		case 0:
			m_pPhase->m_selectNum = MIN(m_pField->getDamageNum(PLY_MY), num);
			if(m_pPhase->m_selectNum > 0){
				m_pField->selLockZoneExcept(PLY_MY, ZONE_DAMAGE);
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "捨てるダメージを%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_CENTER, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}else{
				nextState();
printf("捨てるダメージがありません\n");
			}
			break;
		case 1:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				while(m_pField->getSelectNum() > 0){
if(m_pField->getSelect()->m_reverse==CARD_FRONT){
printf("%sを捨札に置きました\n", m_pField->getSelect()->m_ci.name);
}else{
printf("ダメージを捨札に置きました\n");
}
					m_pField->dumpDamage(PLY_MY, m_pField->getSelect()->m_num);
				}
				nextState();
			}
			break;
	}

	return(m_ret);
}
//! デッキからプログレスを手札に加える
int Skill::seSearchDeckPrg(void)
{
	int	num		= ARGINT(0, -1);	// 加える枚数
	int	isOpen	= ARGINT(1, -1);	// 公開
	int	isUntil	= ARGINT(1, -1);	// まで指定

	switch(m_sState){
		case 0:
			m_pPhase->m_canOpenDlg = true;
			m_pDialog->open(DLG_CARDLIST, DLG_PLACE_CENTER);
			for(int i = 0; i < m_pField->getDeckNum(PLY_MY); i++){
				if(m_pField->getDeck(PLY_MY, i)->m_ci.type == TYPE_PG){
					m_pDialog->m_cardList.addImage(m_pField->getDeck(PLY_MY, i)->m_ci.serNo);
				}
			}
			m_pDialog->m_cardList.m_selMax = MIN(m_pDialog->m_cardList.m_image.size(), (unsigned int)num);
			if(m_pDialog->m_cardList.m_selMax > 0){
				m_sState++;
if(isUntil)printf("デッキから手札に加えるプログレスを%d枚まで選択して下さい\n", m_pDialog->m_cardList.m_selMax);
else printf("デッキから手札に加えるプログレスを%d枚選択して下さい\n", m_pDialog->m_cardList.m_selMax);

			}else{
				m_pDialog->close();
				nextState();
printf("デッキに対象プログレスがいません\n");
			}
			break;
		case 1:{
			VecInt selList;
			m_pDialog->m_cardList.getSelList(&selList);
			m_pDialog->m_btnList[0]->setEnable(isUntil || selList.size() == (unsigned int)m_pDialog->m_cardList.m_selMax);
			if(m_pDialog->m_btnList[0]->isSelect()){
				for(IteInt ite = selList.begin(); ite != selList.end(); ite++){
					for(int i = 0; i < m_pField->getDeckNum(PLY_MY); i++){
						if(m_pField->getDeck(PLY_MY, i)->m_ci.serNo == *ite){
							if(isOpen){
								m_pField->toTemp(PLY_MY, ZONE_DECK, i);
							}else{
								m_pField->searchDeck(PLY_MY, i);
printf("%sを手札に加えました\n", m_pField->getHand(PLY_MY, m_pField->getHandNum(PLY_MY)-1)->m_ci.name);
							}
							break;
						}
					}
					m_pField->fillDeck(PLY_MY);
				}
				m_pDialog->close();
				if(isOpen){
					m_pField->wait();
					m_sState++;
				}else{
					nextState();
				}
			}
			break;
		}
		case 2:
			while(m_pField->getTemp(PLY_MY, 0)){
				m_pField->fromTemp(PLY_MY, ZONE_HAND, m_pField->getHandNum(PLY_MY));
			}
			nextState();
			break;
	}

	return(m_ret);
}
//! 捨札からプログレスを手札に加える
int Skill::seSearchDisCardPrg(void)
{
	int	num		= ARGINT(0, -1);	// 加える枚数
	int	level	= ARGINT(1, -1);	// 対象レベル(def:無)

	switch(m_sState){
		case 0:
			m_pPhase->m_canOpenDlg = true;
			m_pDialog->open(DLG_CARDLIST, DLG_PLACE_CENTER);
			for(int i = 0; i < m_pField->getDisCardNum(PLY_MY); i++){
				if(m_pField->getDisCard(PLY_MY, i)->m_ci.type == TYPE_PG){
					if(level == -1 || m_pField->getDisCard(PLY_MY, i)->m_ci.level <= level){
						m_pDialog->m_cardList.addImage(m_pField->getDisCard(PLY_MY, i)->m_ci.serNo);
					}
				}
			}
			m_pDialog->m_cardList.m_selMax = MIN(m_pDialog->m_cardList.m_image.size(), (unsigned int)num);
			if(m_pDialog->m_cardList.m_selMax > 0){
				m_sState++;
printf("捨札から手札に加えるプログレスを%d枚選択して下さい\n", m_pDialog->m_cardList.m_selMax);
			}else{
				m_pDialog->close();
				nextState();
printf("捨札に対象プログレスがいません\n");
			}
			break;
		case 1:{
			VecInt selList;
			m_pDialog->m_cardList.getSelList(&selList);
			m_pDialog->m_btnList[0]->setEnable(selList.size() == m_pDialog->m_cardList.m_selMax);
			if(m_pDialog->m_btnList[0]->isSelect()){
				for(IteInt ite = selList.begin(); ite != selList.end(); ite++){
					for(int i = 0; i < m_pField->getDisCardNum(PLY_MY); i++){
						if(m_pField->getDisCard(PLY_MY, i)->m_ci.serNo == *ite){
printf("%sを手札に加えました\n", m_pField->getDisCard(PLY_MY, i)->m_ci.name);
							m_pField->searchDisCard(PLY_MY, i);
							break;
						}
					}
					m_pField->fillDisCard(PLY_MY);
				}
				m_pDialog->close();
				nextState();
			}
			break;
		}
	}

	return(m_ret);
}
//! デッキからエナジーに加える
int Skill::seAddEnergy(void)
{
	int	num		= ARGINT(0, -1);	// 加える枚数
	int	isAwake	= ARGINT(1, -1);	// true:アウェイク, false:フォール

	if(m_pPhase->checkDraw(num, m_pField->addEnergy(PLY_MY, isAwake ? true : false))){
		nextState();
printf("エナジーを%d枚セットしました\n", num);
	}

	return(m_ret);
}
//! 捨札からプログレスを置く
int Skill::sePutDisCardPrg(void)
{
	int	num		= ARGINT(0, -1);	// 加える枚数
	int	isAwake	= ARGINT(1, -1);	// true:アウェイク, false:フォール
	int	level	= ARGINT(2, -1);	// 対象レベル(def:無)

	// temp[0-3]: 選択捨札位置
	// temp[9]	: 残り枚数

	switch(m_sState){
		//▼カードリスト生成
		case 0:
			m_pPhase->m_canOpenDlg = true;
			m_pDialog->open(DLG_CARDLIST, DLG_PLACE_CENTER);
			// プログレスを登録
			for(int i = 0; i < m_pField->getDisCardNum(PLY_MY); i++){
				if(m_pField->getDisCard(PLY_MY, i)->m_ci.type == TYPE_PG){
					if(level == -1 || m_pField->getDisCard(PLY_MY, i)->m_ci.level <= level){
						m_pDialog->m_cardList.addImage(m_pField->getDisCard(PLY_MY, i)->m_ci.serNo);
					}
				}
			}
			m_pDialog->m_cardList.m_selMax = MIN(m_pDialog->m_cardList.m_image.size(), (unsigned int)num);
			m_pPhase->m_selectNum = MIN(m_pDialog->m_cardList.m_image.size(), (unsigned int)num);
			if(m_pPhase->m_selectNum > 0){
				m_sState++;
printf("捨札からプレイするプログレスを%d枚選択して下さい\n", num);
			}else{
				m_pDialog->close();
				nextState();
printf("捨札に対象プログレスがいません\n");
			}
			break;
		//▼選択カード記憶
		case 1:{
			VecInt selList;
			m_pDialog->m_cardList.getSelList(&selList);
			m_pDialog->m_btnList[0]->setEnable(selList.size() == m_pPhase->m_selectNum);
			if(m_pDialog->m_btnList[0]->isSelect()){
				MEMARY(m_temp, -1);
				int i = 0;
				for(IteInt ite = selList.begin(); ite != selList.end(); ite++, i++){
					for(int j = 0; j < m_pField->getDisCardNum(PLY_MY); j++){
						if(m_pField->getDisCard(PLY_MY, j)->m_ci.serNo == *ite){
							// 重複チェック
							bool b = true;
							for(int k = 0; k < 10; k++){
								if(m_temp[k] == j){
									b = false;
									break;
								}
							}
							// 位置登録
							if(b){
								m_temp[i] = j;
								break;
							}
						}
					}
				}
				m_pDialog->close();
				m_pPhase->m_canOpenDlg = false;
				m_pField->selLockZoneExcept(PLY_MY, ZONE_PROGRESS);
				m_temp[9] = m_pPhase->m_selectNum;
				m_sState++;
printf("カードを置く位置を選択して下さい\n");
			}
			break;
		}
		//▼捨札から置く
		case 2:
			if(m_temp[9] > 0){
				if(m_pField->getSelect()){
					int prg = m_pField->getSelect()->m_num;
printf("%sをプレイしました\n", m_pField->getSelect()->m_ci.name);
					m_pField->entryDisCard(PLY_MY, m_temp[m_temp[9]-1], prg, isAwake ? true : false);
					m_temp[9]--;
				}
			}else{
				nextState();
			}
			break;
	}

	return(m_ret);
}
//! 自身の攻撃力アップ
int Skill::sePowerUp(void)
{
	int	power	= ARGINT(0, -1);			// 攻撃力上昇値
	int	turn	= ARGINT(1, TURN_MY_END);	// 持続ターン数(def:そのターン中)

	m_card[0]->m_addPower.push_back(TURN_VALUE(power, turn));
	nextState();
printf("%sのパワーを%dアップしました\n", m_card[0]->m_ci.name, power);

	return(m_ret);
}
//! 味方全体の攻撃力アップ
int Skill::sePowerUpAll(void)
{
	int	power	= ARGINT(0, -1);			// 攻撃力上昇値
	int	isMy	= ARGINT(1, -1);			// 自身も対象か
	int	color	= ARGINT(2, -1);			// 対象色(def:無)
	int	turn	= ARGINT(3,	TURN_MY_END);	// 持続ターン数(def:そのターン中)

	for(int i = 0; i < PROGRESS_MAX; i++){
		if(m_pField->getProgress(PLY_MY, i)){
			if(!isMy && i == m_card[0]->m_num){
				continue;
			}
			if(color == -1 || m_pField->getProgress(PLY_MY, i)->m_ci.color == color){
				m_pField->getProgress(PLY_MY, i)->m_addPower.push_back(TURN_VALUE(power, turn));
printf("%sのパワーを%dアップしました\n", m_pField->getProgress(PLY_MY, i)->m_ci.name, power);
			}
		}
	}
	nextState();

	return(m_ret);
}
//! 味方n枚の攻撃力アップ
int Skill::sePowerUpNum(void)
{
	int	power	= ARGINT(0, -1);			// 攻撃力上昇値
	int	num		= ARGINT(1, -1);			// 対象枚数
	int	isMy	= ARGINT(2, -1);			// 自身も対象か
	int	color	= ARGINT(3, -1);			// 対象色(def:無)
	int	turn	= ARGINT(4,	TURN_MY_END);	// 持続ターン数(def:そのターン中)

	switch(m_sState){
		case 0:{
			m_pField->selLockZoneExcept(PLY_MY, ZONE_PROGRESS);
			int selNum = (isMy || m_card[0]->m_ci.type == TYPE_AC ? 0 : 1);
			if(color != -1){
				m_pPhase->m_selectNum = MIN(num, m_pField->getValueNum(PLY_MY, ZONE_PROGRESS, CI_COLOR, color) - selNum);
			}else{
				m_pPhase->m_selectNum = MIN(num, m_pField->getProgressNum(PLY_MY) - selNum);
			}

			if(m_pPhase->m_selectNum > 0){
				if(color != -1){
					m_pField->selLockValueExcept(PLY_MY, ZONE_PROGRESS, CI_COLOR, color);
				}
				if(!isMy){
					m_pField->selLockOnce(PLY_MY, ZONE_PROGRESS, m_card[0]->m_num);
				}
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "パワーアップするプログレスを\n%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_SEEMY, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}else{
				nextState();
printf("パワーアップする対象プログレスがいません\n");
			}
			break;
		}
		case 1:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				for(int i = 0; i < m_pPhase->m_selectNum; i++){
					m_pField->getSelect(i)->m_addPower.push_back(TURN_VALUE(power, turn));
printf("%sのパワーを%dアップしました\n", m_pField->getSelect(i)->m_ci.name, power);
				}
				nextState();
			}
			break;
	}

	return(m_ret);
}
//! 手札n枚ごとに攻撃力アップ
int Skill::sePowerUpHand(void)
{
	int	power	= ARGINT(0, -1);			// 攻撃力上昇値
	int	hand	= ARGINT(1, -1);			// 対象枚数
	int	turn	= ARGINT(2, TURN_MY_END);	// 持続ターン数(そのターン中)

	int pow = (m_pField->getHandNum(PLY_MY) / hand) * power;
	m_card[0]->m_addPower.push_back(TURN_VALUE(pow, turn));
	nextState();
printf("手札が%d枚なので%sのパワーを%dアップしました\n", m_pField->getHandNum(PLY_MY), m_card[0]->m_ci.name, pow);

	return(m_ret);
}
//! エナジーn枚ごとに攻撃力アップ
int Skill::sePowerUpEnergy(void)
{
	int	power	= ARGINT(0, -1);			// 攻撃力上昇値
	int	ene		= ARGINT(1, -1);			// 対象枚数
	int	turn	= ARGINT(2, TURN_MY_END);	// 持続ターン数(そのターン中)

	int pow = (m_pField->getEnergyNum(PLY_MY) / ene) * power;
	m_card[0]->m_addPower.push_back(TURN_VALUE(pow, turn));
	nextState();
printf("エナジーが%d枚なので%sのパワーを%dアップしました\n", m_pField->getEnergyNum(PLY_MY), m_card[0]->m_ci.name, pow);

	return(m_ret);
}
//! 自身のストライクアップ
int Skill::seStrikeUp(void)
{
	int	strike	= ARGINT(0, -1);			// ストライク上昇値
	int	turn	= ARGINT(1, TURN_MY_END);	// 持続ターン数(そのターン中)

	m_card[0]->m_addStrike.push_back(TURN_VALUE(strike, turn));
	nextState();
printf("%sのストライクを%dアップしました\n", m_card[0]->m_ci.name, strike);

	return(m_ret);
}
//! 相手プログレスを手札に戻す
int Skill::seBouncePrg(void)
{
	int	num		= ARGINT(0, -1);	// 戻す枚数
	int	level	= ARGINT(1, -1);	// 対象レベル(def:無)

	switch(m_sState){
		case 0:
			m_pField->selLockZoneExcept(PLY_OPPO, ZONE_PROGRESS);
			if(level != -1){
				m_pPhase->m_selectNum = MIN(m_pField->getValueNum(PLY_OPPO, ZONE_PROGRESS, CI_LEVEL, level, "<="), num);
			}else{
				m_pPhase->m_selectNum = MIN(m_pField->getProgressNum(PLY_MY), num);
			}
			if(m_pPhase->m_selectNum > 0){
				if(level != -1){
					m_pField->selLockValueExcept(PLY_OPPO, ZONE_PROGRESS, CI_LEVEL, level, "<=");
				}
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "手札に戻すプログレスを%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_SEEOPPO, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}else{
				nextState();
printf("手札に戻す対象プログレスがいません\n");
			}
			break;
		case 1:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				while(m_pField->getSelect()){
printf("%sを相手の手札に戻しました\n", m_pField->getSelect()->m_ci.name);
					m_pField->bounceProgress(PLY_OPPO, m_pField->getSelect()->m_num);
				}
				nextState();
			}
			break;
	}

	return(m_ret);
}
//! 相手プログレスをデッキに戻す
int Skill::seBouncePrgDeck(void)
{
	int	num		= ARGINT(0, -1);	// 戻す枚数
	int	place	= ARGINT(1, -1);	// 戻す場所
	int	level	= ARGINT(2, -1);	// 対象レベル(def:無)

	switch(m_sState){
		case 0:
			m_pField->selLockZoneExcept(PLY_OPPO, ZONE_PROGRESS);
			if(level != -1){
				m_pPhase->m_selectNum = MIN(m_pField->getProgressNum(PLY_MY), num);
			}else{
				m_pPhase->m_selectNum = MIN(m_pField->getValueNum(PLY_OPPO, ZONE_PROGRESS, CI_LEVEL, level, "<="), num);
			}

			if(m_pPhase->m_selectNum > 0){
				if(level != -1){
					m_pField->selLockValueExcept(PLY_OPPO, ZONE_PROGRESS, CI_LEVEL, level, "<=");
				}
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "デッキに戻すプログレスを%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_SEEOPPO, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}else{
				nextState();
printf("デッキに戻す対象プログレスがいません\n");
			}
			break;
		case 1:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				while(m_pField->getSelect()){
					if(place == DIR_UP){
printf("%sを相手のデッキトップに戻しました\n", m_pField->getSelect()->m_ci.name);
						int sel = m_pField->getSelect()->m_num;
						m_pField->backProgress(PLY_OPPO, sel, m_pField->getDeckNum(PLY_OPPO));
					}else if(place == DIR_DOWN){
printf("%sを相手のデッキ下に戻しました\n", m_pField->getSelect()->m_ci.name);
						m_pField->liftDeck(PLY_OPPO);
						int sel = m_pField->getSelect()->m_num;
						m_pField->backProgress(PLY_OPPO, sel, 0);
					}
				}
				nextState();
			}
			break;
	}

	return(m_ret);
}
//! 相手プログレスを退却
int Skill::seRemovePrg(void)
{
	int	num		= ARGINT(0, -1);	// 退却枚数
	int	level	= ARGINT(1, -1);	// 対象レベル(def:無)

	switch(m_sState){
		case 0:
			m_pField->selLockZoneExcept(PLY_OPPO, ZONE_PROGRESS);
			if(level != -1){
				m_pPhase->m_selectNum = MIN(m_pField->getProgressNum(PLY_MY), num);
			}else{
				m_pPhase->m_selectNum = MIN(m_pField->getValueNum(PLY_OPPO, ZONE_PROGRESS, CI_LEVEL, level, "<="), num);
			}

			if(m_pPhase->m_selectNum > 0){
				if(level != -1){
					m_pField->selLockValueExcept(PLY_OPPO, ZONE_PROGRESS, CI_LEVEL, level, "<=");
				}
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "退却させるプログレスを%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_SEEOPPO, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}else{
				nextState();
printf("退却させる対象プログレスがいません\n");
			}
			break;
		case 1:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				while(m_pField->getSelect()){
printf("%sを退却させました\n", m_pField->getSelect()->m_ci.name);
					m_pField->dumpProgress(PLY_OPPO, m_pField->getSelect()->m_num);
				}
				nextState();
			}
			break;
	}

	return(m_ret);
}
//! 手札と表ダメージを入れ替える
int Skill::seChangeHandDamage(void)
{
	int	num	= ARGINT(0, -1);	// 入れ替え枚数

	// card[1〜n]	: 選択手札
	// card[n+1〜m]	: 選択ダメージ

	switch(m_sState){
		case 0:
			m_pField->selLockZoneExcept(PLY_MY, ZONE_HAND);
			m_pPhase->m_selectNum = MIN(MIN(m_pField->getHandNum(PLY_MY), m_pField->getValueNum(PLY_MY, ZONE_DAMAGE, CD_REVERSE, CARD_FRONT)), num);
			if(m_pPhase->m_selectNum > 0){
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "入れ替える手札を%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_CENTER, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}else{
				nextState();
printf("入れ替えできる対象カードがありません\n");
			}
			break;
		case 1:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				for(int i = 0; i < m_pPhase->m_selectNum; i++){
					m_card[1 + i] = m_pField->getSelect(i);
				}
				m_pField->selLockValueExcept(PLY_MY, ZONE_DAMAGE, CD_REVERSE, CARD_FRONT);
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "入れ替えるダメージを%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_CENTER, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}
			break;
		case 2:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				for(int i = 0; i < m_pPhase->m_selectNum; i++){
					m_card[1 + m_pPhase->m_selectNum + i] = m_pField->getDamage(PLY_MY, i);
				}
				m_sState++;
			}
			break;
		case 3:
			for(int i = 0; i < m_pPhase->m_selectNum; i++){
				m_pField->replaceCard(m_card[1 + i], m_card[1 + m_pPhase->m_selectNum + i], true, true, true, true);
printf("%sと%sを入れ替えました\n", m_card[1 + i]->m_ci.name, m_card[1 + m_pPhase->m_selectNum + i]->m_ci.name);
			}
			nextState();
			break;
	}

	return(m_ret);
}
//! ダメージを表にする
int Skill::seDamageFront(void)
{
	int	num	= ARGINT(0, -1);	// 対象枚数

	switch(m_sState){
		case 0:
			m_pPhase->m_selectNum = MIN(m_pField->getValueNum(PLY_MY, ZONE_DAMAGE, CD_REVERSE, CARD_BACK), num);
			if(m_pPhase->m_selectNum > 0){
				m_pField->selLockValueExcept(PLY_MY, ZONE_DAMAGE, CD_REVERSE, CARD_BACK);
				m_sState++;

				m_pPhase->m_canOpenDlg = true;
				char text[256] = {};
				wsprintf(text, "表にするダメージを%d枚選択して下さい", m_pPhase->m_selectNum);
				m_pDialog->open(DLG_TEXT, DLG_PLACE_CENTER, NULL, text);
				m_pPhase->m_canOpenDlg = false;
			}else{
				nextState();
printf("表にするダメージがありません\n");
			}
			break;
		case 1:
			if(m_pField->getSelectNum() == m_pPhase->m_selectNum){
				for(int i = 0; i < m_pPhase->m_selectNum; i++){
					m_pField->reverseDamage(PLY_MY, m_pField->getSelect(i)->m_num, true);
printf("%sを表にしました\n", m_pField->getSelect(i)->m_ci.name);
				}
			}
			nextState();
			break;
	}

	return(m_ret);
}
//! デッキトップを上か捨札に置く
int Skill::seDeckTopMoveTorD(void)
{
	switch(m_sState){
		case 0:
			m_pField->reverseDeck(PLY_MY, m_pField->getDeckNum(PLY_MY)-1, true);
			m_sState++;
			m_pPhase->m_canOpenDlg = true;
			m_pDialog->open(DLG_T_UPDUMP, DLG_PLACE_CENTER, m_card[0], "デッキトップと捨札どちらに置きますか？");
			break;
		case 1:
			if(LOWORD(m_pDialog->getResult()) == BTN_ID_UP){
				m_pField->reverseDeck(PLY_MY, m_pField->getDeckNum(PLY_MY)-1, false);
				nextState();
printf("%sをデッキトップに戻しました\n", m_pField->getDeck(PLY_MY, m_pField->getDeckNum(PLY_MY)-1)->m_ci.name);
			}else if(LOWORD(m_pDialog->getResult()) == BTN_ID_DISCARD){
printf("%sを捨札に置きました\n", m_pField->getDeck(PLY_MY, m_pField->getDeckNum(PLY_MY)-1)->m_ci.name);
				m_pField->dumpDeck(PLY_MY, m_pField->getDeckNum(PLY_MY)-1);
				m_pDialog->close();
				nextState();
			}
			break;
	}

	return(m_ret);
}

