/**
 * 異なる位置にある2つの点AB間の距離を取得する
 * 
 * @param {Integer} ax 点Aのx座標
 * @param {Integer} ay 点Aのy座標
 * @param {Integer} bx 点Bのx座標
 * @param {Integer} by 点Bのy座標
 * @return {Integer} 点AB間の距離
 */
function GetGapLength( ax, ay, bx, by ){
	return ( ( bx - ax ) ^ 2 + ( by - ay ) ^ 2 ) ^ 0.5;
}

/**
 * 点Aから異なる位置にある点Bへの絶対角度を取得する
 * 
 * @param {Integer} ax 点Aのx座標
 * @param {Integer} ay 点Aのy座標
 * @param {Integer} bx 点Bのx座標
 * @param {Integer} by 点Bのy座標
 * @return {Integer} 点Aから点Bへの絶対角度
 */
function GetGapAngle( ax, ay, bx, by ){
	return atan2( by - ay, bx - ax );
}

/**
 * 点Aからある距離、絶対角度にある点Bのx座標を取得する
 * 
 * @param {Integer} ax        点Aのx座標
 * @param {Integer} gaplength 点Bまでの距離
 * @param {Integer} gapangle  点Bへの絶対角度
 * @return {Integer} 点Bのx座標
 */
function GetGapX( ax, gaplength, gapangle ){
	return ax + gaplength * cos( gapangle );
}

/**
 * 点Aからある距離、絶対角度にある点Bのy座標を取得する
 * 
 * @param {Integer} ay        点Aのy座標
 * @param {Integer} gaplength 点Bまでの距離
 * @param {Integer} gapangle  点Bへの絶対角度
 * @return {Integer} 点Bのy座標
 */
function GetGapY( ay, gaplength, gapangle ){
	return ay + gaplength * sin( gapangle );
}

/**
 * 与えられた角度を0以上360未満にして返す
 * 
 * @param {Integer} angle 角度
 * @return {Integer} 調整された角度
 */
function RollAngle( angle ){
	return ( ( angle % 360 ) + 360 ) % 360;
}

/**
 * 角度補正ホーミング関数
 * 
 * @param {Integer} x      現在位置のx座標
 * @param {Integer} y      現在位置のy座標
 * @param {Integer} tox    追尾目標のx座標
 * @param {Integer} toy    追尾目標のy座標
 * @param {Integer} nangle 現在の角度
 * @param {Integer} dangle 角度補正量最大値
 * @return {Integer} ホーミング補正後の角度
 */
function AngleSearch( x, y, tox, toy, nangle, dangle ){
	let TargetAngle = atan2( toy - y, tox - x );
	let ICross = cos( nangle - TargetAngle );
	let CCross = cos( dangle );
	
	if( ICross < CCross ){
		let LCross = cos( nangle - dangle - TargetAngle );
		let RCross = cos( nangle + dangle - TargetAngle );
		if( LCross > RCross ){
			nangle -= dangle;
		}else{
			nangle += dangle;
		}
	}else{
		nangle = TargetAngle;
	}
	
	return nangle;
}

/**
 * 点(x,y)から角度angleで引かれる線分と壁との交点、反射角を返す
 * 
 * @param {Integer} x     指定点のx座標
 * @param {Integer} y     指定点のy座標
 * @param {Integer} angle 線分を引く角度
 * @return {Array} 壁との交点、反射角[rx,ry,rangle]
 */
function GetReflectData( x, y, angle ){
	let rx = 0;
	let ry = 0;
	let rangle = 0;
	
	// 線分にするための終点を設定
	let tox = x + cos( angle ) * 800;	// 適当に大きい数値で終点を作成
	let toy = y + sin( angle ) * 800;	// 適当に大きい数値で終点を作成
	
	// 簡略化のため。同様の変数を宣言している場合には消してもOK
	let MinX = GetClipMinX();
	let MaxX = GetClipMaxX();
	let MinY = GetClipMinY();
	let MaxY = GetClipMaxY();
	
	// 上下左右に対して判定を行う
	let PosU = Collision_Line_Line( x, y, tox, toy, MinX, MinY, MaxX, MinY );
	let PosL = Collision_Line_Line( x, y, tox, toy, MinX, MinY, MinX, MaxY );
	let PosR = Collision_Line_Line( x, y, tox, toy, MaxX, MinY, MaxX, MaxY );
	let PosB = Collision_Line_Line( x, y, tox, toy, MinX, MaxY, MaxX, MaxY );
	
	// 結果によってどの壁で反射するかを選択 上下左右の順で判定されます
	if( PosU[ 0 ] != NULL ){
		// 上だった
		rx = PosU[ 0 ];
		ry = PosU[ 1 ];
		rangle = -angle;
	}else if( PosB[ 0 ] != NULL ){
		// 下だった
		rx = PosB[ 0 ];
		ry = PosB[ 1 ];
		rangle = -angle;
	}else if( PosL[ 0 ] != NULL ){
		// 左だった
		rx = PosL[ 0 ];
		ry = PosL[ 1 ];
		rangle = 180 - angle;
	}else if( PosR[ 0 ] != NULL ){
		// 右だった
		rx = PosR[ 0 ];
		ry = PosR[ 1 ];
		rangle = 180 - angle;
	}else{
		// どこにも反射してない場合、ダミーとして元の値をセット
		rx = x;
		ry = y;
		rangle = angle;
	}
	
	return [ rx, ry, rangle ];
}

/**
 * 線分(x1,y1)-(x2,y2)と線分(x3,y3)-(x4,y4)の交点を返す
 * 
 * @param {Integer} x1 線分1の始点x座標
 * @param {Integer} y1 線分1の始点y座標
 * @param {Integer} x2 線分1の終点x座標
 * @param {Integer} y2 線分1の終点y座標
 * @param {Integer} x3 線分2の始点x座標
 * @param {Integer} y3 線分2の始点y座標
 * @param {Integer} x4 線分2の終点x座標
 * @param {Integer} y4 線分2の終点y座標
 * @return {Array} 2線分の交点[x,y] 交差しなかった場合には[NULL,NULL]が返る
 */
function Collision_Line_Line( x1, y1, x2, y2, x3, y3, x4, y4 ){
	let f1 = x2 - x1;
	let g1 = y2 - y1;
	let f2 = x4 - x3;
	let g2 = y4 - y3;
	
	let det = ( f2 * g1 ) - ( f1 * g2 );
	
	// detの値が0(2線分が水平)の場合交点が存在しないので戻る
	if( det == 0 ){
		return [ NULL, NULL ];
	}else{
		// それ以外の場合、交点を計算
		let dx = x3 - x1;
		let dy = y3 - y1;
		let t1 = ( f2 * dy - g2 * dx ) / det;
		let t2 = ( f1 * dy - g1 * dx ) / det;
		
		// 交点が線分の中に存在するなら数値を計算
		if( ( 0 <= t1 && t1 <= 1 ) && ( 0 <= t2 && t2 <= 1 ) ){
			let rx = x1 + t1 * f1;
			let ry = y1 + t1 * g1;
			
			return [ rx, ry ];
		}else{
			// もし交点が線分の延長線にある場合、交点なしとする
			return [ NULL, NULL ];
		}
	}
}

/**
 * 数値を整数文字列に変換する。
 *
 * @param {Integer} no 変換対象数値
 * @return 整数文字列
 */
function IntToString( no ){
		//戻り値の初期化
		let number = "";
		let numberString = ToString( no );
		//小数点の前までを文字列として取得して返す
		let i = 0;
		while( i < length( numberString ) ){
				let char = numberString[ i ];
				if( char == '.' ){
					break;
				}
				number = number ~ [ char ];
				i += 1;
		}
		return number;
}

/**
 * 数値を整数文字列に変換する。その2
 *
 * @param {Integer} no 変換対象数値
 * @return 整数文字列
 */
function IntToString2( no ){
	let leng = 0;
	if( no > 0 ){
		leng = truncate( log10(  no ) ) + 1;
	}else if( no == 0 ){
		leng = 1;
	}else{
		leng = truncate( log10( -no ) ) + 2;
	}
	
	let string = ToString( no );
	let number = string[ 0..int( leng ) ];
	
	return number;
}