nyama++¤µ¤ó¤Î¥×¥í¥°¥é¥à¥½¡¼¥¹

/*
	¥Ï¥ë¸¦µæ½ê¥×¥í¥°¥é¥ß¥ó¥°¥³¥ó¥Æ¥¹¥È2009±þÊçºîÉÊ
	Author: nyama++

	¡Ú¤Ï¤¸¤á¤Ë¡Û
		º£²ó¤Ï¤¢¤Þ¤ê»þ´Ö¤¬¤Ê¤¯¥¹¥³¥¢¤ò¾å¤²¤ë¤Î¤Ëɬ»à¤À¤Ã¤¿¤Î¤Ç¡¢¤È¤³¤í¤É¤³¤í¤Ë¥Ð¥°¤¬¤¢¤ë¤Î¤òÊüÃÖ¤·¤Æ¤¤¤¿¤ê¡¢
		»È¤Ã¤Æ¤Ê¤¤ÊÑ¿ô¤¬»Ä¤Ã¤Æ¤¤¤¿¤ê¡¢ÌµÂ̤ʽèÍý¤¬Â¿¤«¤Ã¤¿¤ê¡¢¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤¬¤¿¤¯¤µ¤ó¤¢¤Ã¤¿¤ê¡¢
		¥³¡¼¥É¤¬±ø¤«¤Ã¤¿¤ê¤·¤Þ¤¹¡£¤´¤á¤ó¤Ê¤µ¤¤¡£

	¡Ú¥¢¥ë¥´¥ê¥º¥à¤Î³µÍסÛ
		º£²ó¹Í¤¨¤¿¥¢¥ë¥´¥ê¥º¥à¤ÏÂ礭¤¯¤ï¤±¤Ç2¤Ä¤Î½èÍý¤Ë¤ï¤«¤ì¤Þ¤¹¡£
			1. ¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤òºîÀ®
			2. ¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤òÄ̲ᤷ¤Ê¤¬¤é¥´¡¼¥ë¤Ø¸þ¤«¤¦¥¢¥¯¥·¥ç¥ó¤ÎºîÀ®

		¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤ÎºîÀ®¤Ç¤Ï¡¢¤Þ¤º¥¹¥¿¡¼¥ÈÃÏÅÀ¡¢¥´¡¼¥ë¡¢·ê¤Î»Í¶ù¤Ê¤É¤ËĺÅÀ¤ò¼è¤ê¡¢³ÆÄºÅÀ¤òľÀþ¤Ç·ë¤Ó
		¤½¤ÎÃæ¤«¤é·ê¤È¸òº¹¤¹¤ëľÀþ¤ò½ü¤­¤Þ¤¹¡£¤¹¤ë¤È¡¢¥°¥é¥Õ¹½Â¤¤¬¤Ç¤­¤ë¤Î¤Ç¡¢ÄºÅÀ´Ö¤Îµ÷Î¥¤ò¥³¥¹¥È¤È¤·¤Æ
		¥À¥¤¥¯¥¹¥È¥éË¡¤Ç¤³¤ì¤ò²ò¤­¤Þ¤¹¡£¤³¤Î¤È¤­µá¤á¤é¤ì¤¿²ò¤ÎĺÅÀ¤¬¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤Ë¤Ê¤ê¤Þ¤¹¡£

		¼¡¤Ë¤½¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤òÄ̲ᤷ¤Ê¤¬¤é¥´¡¼¥ë¤Ø¸þ¤«¤¦¥¢¥¯¥·¥ç¥ó¤òºîÀ®¤·¤Þ¤¹¡£Ã±½ã¤Ê¥¢¥ë¥´¥ê¥º¥à¤Ç¤Ï
		¸½ºß°ÌÃ֤ȼ¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤ò·ë¤ÖľÀþ¾å¤ò²Ã®¤·¤Ê¤¬¤é¿Ê¤ß¡¢¤½¤ÎľÀþ¤Îü¤ÇÄä»ß¤Ç¤­¤ë¤è¤¦¤Ë®ÅÙ¤ò
		Íî¤È¤·¤Æ¡¢Ã¼¤ÇÄä»ß¤·¤¿¤é¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤Þ¤ÇƱ¤¸¤è¤¦¤Ë¿Ê¤à¡¢¤È¤¤¤¦¤Î¤ò·«¤êÊÖ¤¹¤³¤È¤Ç¥´¡¼¥ë¤Ç¤­¤Þ¤¹¡£
		¤³¤Îñ½ã¤Ê¥¢¥ë¥´¥ê¥º¥à¤À¤±¤Ç¤â96ËüÅÀ¤Û¤É¼è¤ì¤Þ¤¹¤¬¡¢¶Ê¤¬¤ë¤¿¤Ó¤ËÄä»ß¤·¤Æ¤¤¤ë¤Î¤Ç¥é¥ó¥­¥ó¥°¾å°Ì¤Ë
		Æþ¤ë¤Ë¤Ï¸úΨ¤¬°­¤¹¤®¤Þ¤¹¡£

		¤½¤³¤Ç¡¢¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤´¤È¤ËÄä»ß¤·¤Ê¤¯¤Æ¤âºÑ¤à¤è¤¦¤Ë¡¢¤É¤ÎÊý¸þ¤Ë¤É¤ì¤À¤±²Ã®¤¹¤ì¤Ð¤¤¤¤¤Î¤«¤ò¿ä¬¤¹¤ë
		´Ø¿ô¤òƳÆþ¤·¤Þ¤¹¡£¤¿¤À¤·¡¢¤³¤ì¤Ïñ¤Ê¤ë¿ä¬¤Ç¤·¤«¤Ê¤¤¤¿¤á¤³¤Î¿ä¬¤Ë½¾¤¦¤È·ê¤ËÍî¤Á¤Æ¤·¤Þ¤¦¤³¤È¤â¤¢¤ê¤¨¤Þ¤¹¡£
		¤½¤Î¤¿¤á¡¢¿ä¬¤Ë½¾¤Ã¤Æ·ê¤ËÍî¤Á¤¿¾ì¹ç¤ä¤Ê¤«¤Ê¤«¥´¡¼¥ë¤Ç¤­¤Ê¤¤¾ì¹ç¤Ï¡¢1¤ÄÁ°¤ËÌá¤Ã¤Æ¿ä¬¤µ¤ì¤¿Êý¸þ¤ò¤Á¤ç¤Ã¤È
		½¤Àµ(45¡ë²óž¤µ¤»¤¿¤ê¡¢90¡ë²óž¤µ¤»¤ë)¤·¤Æ¡¢¤½¤ÎÊý¸þ¤Ë¿Ê¤ß¤Þ¤¹¡£½¤Àµ¤·¤¿¤â¤Î¤ò»î¤·¤Æ¤â²ò·è¤·¤Ê¤¤¾ì¹ç¤Ë¤Ï
		¥Ö¥ì¡¼¥­¤ò¤«¤±¤Þ¤¹¡£¤Ä¤Þ¤ê¡¢¿ä¬¤µ¤ì¤¿¥Ù¥¯¥È¥ë + ¤½¤Î½¤ÀµÈÇ¡ß4Êý¸þ + ¥Ö¥ì¡¼¥­ ¤Î6¤Ä¤Î¥¢¥¯¥·¥ç¥ó¤ò
		ÁªÂò¤·¤Ê¤¬¤éõº÷¤ò¤·¤Þ¤¹¡£

		¤É¤ÎÊý¸þ¤Ë¤É¤ì¤À¤±²Ã®¤¹¤ì¤Ð¤¤¤¤¤Î¤«¤ò¿ä¬¤¹¤ë´Ø¿ô¤Ï¡¢¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤¬¥´¡¼¥ë¤«Èݤ«¤Ç½èÍý¤òʬ¤±¤Þ¤¹¡£
		¼¡¤¬¥´¡¼¥ë¤Î¾ì¹ç¤Ïñ½ã¤Ç¡¢¥´¡¼¥ë¤Î¤¢¤ëÊý¸þ¤Ø¿Ê¤à¤è¤¦¤Ë¤¹¤ë¤À¤±¤Ç¤¹¡£¸½ºß¥Ü¡¼¥ë¤Î¿Ê¤ó¤Ç¤¤¤ëÊý¸þ¤¬¥´¡¼¥ë¤È¤Ï
		Á´Á³°ã¤¦Êý¸þ¤Ç¤¢¤ì¤Ð¥Ö¥ì¡¼¥­¤ò¤«¤±¤Ä¤Ä¡¢¿Ê¤àÊý¸þ¤ò¥´¡¼¥ë¤ÎÊý¸þ¤Ø½¤Àµ¤·¤Þ¤¹¡£
		¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤¬¥´¡¼¥ë¤Ç¤Ê¤±¤ì¤Ð¡¢°Ê²¼¤Î4¤Ä¤«¤é¹Ôư¤òÁªÂò¤·¤Þ¤¹¡£
			[1]. ¼¡¤Î¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥ÈÊý¸þ¤Ë¶Ê¤¬¤ë
			[2]. ¤Þ¤À¶Ê¤¬¤ê»Ï¤á¤ë¤Ë¤ÏÁ᤯¡¢¶Ê¤¬¤ë¤¿¤á¤ËµÕÊý¸þ¤Ø°Üư¤·¤Æ¤ª¤¯É¬Íפâ¤Ê¤¤¤Î¤Ç¡¢¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥ÈÊý¸þ¤ØÄ¾¿Ê
			[3]. ¤³¤Î¤Þ¤Þľ¿Ê¤¹¤ë¤È¶Ê¤¬¤ê¤­¤ì¤Ê¤¯¤Ê¤ë¤Î¤Ç¡¢¼¡¤Î¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥ÈÊý¸þ¤È¤ÏµÕ¤Ë°Üư¤·¤Æ¤ª¤¯
			[4]. ¤³¤Î¤Þ¤Þ¤À¤È¶Ê¤¬¤ê¤­¤ì¤½¤¦¤Ë¤Ê¤¤¤Î¤Ç¡¢¾¯¤·¥Ö¥ì¡¼¥­¤ò¤«¤±¤Ä¤Ä¼¡¤Î¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥ÈÊý¸þ¤Ë¶Ê¤¬¤ë
		°Ê²¼¤Î¥¢¥¹¥­¡¼¥¢¡¼¥È¤ÇÀâÌÀ¤¹¤ë¤È¡¢¸½ºß¤Î°ÌÃÖ¡û¤«¤é¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È­¡¤òÄ̤ꡢ¼¡¤Î¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È­¢¤Ë
		¿Ê¤à¾ì¹ç¡¢¢ª¤Ë¶Ê¤¬¤Ã¤Æ·ê¤ËÍî¤Á¤Ê¤±¤ì¤Ð¶Ê¤¬¤ë(¹Ôư[1])¡¢¤¿¤À¤·¢¬¤Ø¤Î®ÅÙ¤¬Â礭¤¤¤È´Ö¤¬¤ê¤­¤ì¤Ê¤¤¤Î¤Ç¥Ö¥ì¡¼¥­¤ò
		¤«¤±¤ë(¹Ôư[4])¤«¡¢¾¯¤·¢«¤Ë¶Ê¤¬¤Ã¤Æ¤ª¤­¤Þ¤¹(¹Ôư[3])¡£¢ª¤Ë¶Ê¤¬¤ë¤È·ê¤ËÍî¤Á¤Æ¤·¤Þ¤¦¾ì¹ç¤Ï¡¢°ìö¢«¤Ë¶Ê¤¬¤Ã¤Æ
		¥¹¥à¡¼¥º¤Ë­¢¤ÎÊý¤Ø¶Ê¤¬¤ì¤ë¤è¤¦¤Ë½àÈ÷¤¹¤ë(¹Ôư[3])¤«¡¢­¡Êý¸þ¤ØÄ¾¿Ê¤·¤Æ·ê¤ËÍî¤Á¤º¤Ë¶Ê¤¬¤ì¤ë¤è¤¦¤Ë¤Ê¤ë¤Î¤ò
		ÂÔ¤Á¤Þ¤¹(¹Ôư[2])¡£

			   ­¡            ­¢
			    ¢£¢£¢£¢£¢£¢£¢£
			    ¢£¢£¢£¢£¢£¢£¢£
			    ¢£¢£¢£¢£¢£¢£¢£
			    ¢£¢£¢£¢£¢£¢£¢£
			    ¢£¢£¢£·ê¢£¢£¢£
			¡û  ¢£¢£¢£¢£¢£¢£¢£
			    ¢£¢£¢£¢£¢£¢£¢£
			    ¢£¢£¢£¢£¢£¢£¢£

		°Ê¾å¤¬º£²ó¼ÂÁõ¤·¤¿¥¢¥ë¥´¥ê¥º¥à¤Î³µÍפǤ¹¡£
	
	¡Ú¤½¤Î¾¡¢ºÙ¤«¤¤¥Ý¥¤¥ó¥È¡Û
		¡Ú1. ¥¸¥ã¥ó¥×¤ò¹Íθ¤·¤¿¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¥ê¥¹¥È¤âºî¤ë¡Û
			ĺÅÀ¤ò·ë¤ÖľÀþ¤È·ê¤Î¶ë·Á¤Î¸òº¹¤·¤Æ¤¤¤ëŤµ¤¬MAX_VEL(4.0f)°Ê²¼¤Ê¤é¤Ð¥¸¥ã¥ó¥×¤Ç¤­¤ë²ÄǽÀ­¤¬¤¢¤ë¤Î¤Ç
			³Î¼Â¤Ë¥¸¥ã¥ó¥×¤Ç¤­¤ë¤È²¾Äꤷ¤¿¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¥ê¥¹¥È¤âºî¤ê¤Þ¤¹¡£¤¢¤È¤Ï¾å¤ÇÀâÌÀ¤·¤¿¤Î¤ÈƱÍͤ˽èÍý¤ò
			¤¹¤ì¤Ðõº÷¤ò¤¹¤ëÉôʬ¤¬¤¦¤Þ¤¯Æ¯¤¤¤Æ·ê¤ËÍî¤Á¤Ê¤¤¤è¤¦¤Ë¿Ê¤ó¤Ç¤¯¤ì¤Þ¤¹¡£
			¤¿¤À¤·¡¢¥¸¥ã¥ó¥×²Äǽ¤«¤É¤¦¤«¤ÎȽÄê»þ¤Ë¥Ü¡¼¥ë¤Î®ÅÙ¤ò¹Íθ¤·¤Æ¤¤¤Ê¤¤¤¿¤á¡¢Â®ÅÙ¤¬Â­¤ê¤º¤É¤¦¤·¤Æ¤â
			¥¸¥ã¥ó¥×¤¬¤Ç¤­¤Ê¤¤¤³¤È¤¬¤¢¤ê¤Þ¤¹¡£¤½¤Î¾ì¹ç¤Ç¤â·ê¤ò±ª²ó¤·¤Æ¤Ê¤ó¤È¤«¥´¡¼¥ë¤Ë¸þ¤«¤Ã¤Æ¤¯¤ì¤Þ¤¹¤¬¡¢
			̵ÂÌ¤ÊÆ°¤­¤¬Â¿¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¤¤Þ¤¹¡£¤½¤Î¤¿¤á¡¢¥¸¥ã¥ó¥×¤¢¤ê¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¥ê¥¹¥È¤È¡¢¥¸¥ã¥ó¥×¤Ê¤·¤Î
			¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¥ê¥¹¥È¤Î2¤Ä¤òºî¤ê¡¢Î¾Êý»î¤·¤ÆÎɤ¤·ë²Ì¤ò½Ð¤·¤¿Êý¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¥ê¥¹¥È¤òºÎÍѤ·¤Þ¤¹¡£
		
		¡Ú2. ¥À¥¤¥¯¥¹¥È¥é¤Ç¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¥ê¥¹¥È¤òºîÀ®¤¹¤ëºÝ¤Ë¡¢¶Ê¤¬¤ë¥³¥¹¥È¤â¹Í¤¨¤ë¡Û
			¥À¥¤¥¯¥¹¥È¥é¤Çµá¤á¤ë¥ë¡¼¥È¤ÏľÀþµ÷Î¥¤Ç¤ÏºÇû¤Ç¤âS»ú¥«¡¼¥Ö¤Î¤è¤¦¤Ê¥ë¡¼¥È¤ò´Þ¤ó¤Ç¤¤¤ë¤È·ë²ÌŪ¤ËÃÙ¤¯¤Ê¤Ã¤Æ
			¤·¤Þ¤¦¤³¤È¤¬¤¢¤ê¤Þ¤¹¡£¤½¤³¤Ç¡¢¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤ò·ë¤Ö¥¨¥Ã¥¸¤ÎÀܳ³ÑÅÙ¤ò¹Íθ¤·¤Æ¥³¥¹¥È¤ò·×»»¤·¤Æ¤ä¤ë¤È
			ñ½ã¤ËºÇû¤Ê¥ë¡¼¥È¤òÁª¤Ö¤Î¤Ç¤Ï¤Ê¤¯¡¢Â®ÅÙ¤òÍî¤È¤µ¤º¤Ë¶Ê¤¬¤ê¤ä¤¹¤¯¤½¤ì¤Ê¤ê¤Ëû¤¤¥ë¡¼¥È¤òÁªÂò¤·¤Æ¤¯¤ì¤ë¤è¤¦¤Ë
			¤Ê¤ê¤Þ¤¹¡£
		
		¡Ú3. ¥´¡¼¥ëÉÕ¶á¤Ç¤Ï¥´¡¼¥ë¤Î»Í¶ù¤ÈÃæ¿´¤ËĺÅÀ¤ò¼è¤ë¡Û
			¥¹¥³¥¢¤Ë¤Ï¶Ï¤«¤Ê±Æ¶Á¤·¤«¤¢¤ê¤Þ¤»¤ó¤¬¡¢¾¯¤·¥¹¥³¥¢¤¬¾å¤¬¤ë¤Î¤Ç¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¥ê¥¹¥È¤òºîÀ®¤¹¤ëºÝ¤Ë
			¥´¡¼¥ë¤Î»Í¶ù¤ÈÃæ¿´¤Î¹ç·×5²Õ½ê¤ËĺÅÀ¤ò¼è¤ê¤Þ¤¹¡£

		¡Ú4. ·ê¤È·ê¤Î¸òÅÀÉÕ¶á¤Ë¤âĺÅÀ¤ò¼è¤ë¡Û
			·ê¤È·ê¤Î¸òÅÀÉÕ¶á¤Ë¤âĺÅÀ¤ò¼è¤ë¤³¤È¤Ç¡¢¸òº¹¤·¤Æ¤¤¤ëÉôʬ¤ò¼Ð¤á¤Ë¥¸¥ã¥ó¥×¤Ç¤­¤ë¥ë¡¼¥È¤òȯ¸«¤Ç¤­¤ë¤³¤È¤¬
			¤¢¤ê¤Þ¤¹¡£°Ê²¼¤Î¥¢¥¹¥­¡¼¥¢¡¼¥È¤Ç¤Ï­¡¤«¤é­¢¤Ø¤Î¥¸¥ã¥ó¥×¤Ë¤Ê¤ê¤Þ¤¹¡£

			¢£¢£¢£¢£¢£¢£¢£
			¢£¢£¢£·ê¢£¢£¢£­¢
			¢£¢£¢£¢£¢£¢£¢£¢£¢£¢£¢£¢£¢£
			¢£¢£¢£¢£¢£¢£¢£¢£¢£¢£¢£¢£¢£
			¡¡¡¡¡¡¡¡¡¡­¡¢£¢£¢£·ê¢£¢£¢£
			¡¡¡¡¡¡¡¡¡¡¡¡¢£¢£¢£¢£¢£¢£¢£

		¡Ú5. ¥´¡¼¥ë¤ò¸«¤Ä¤±¤Æ¤â¤è¤êÎɤ¤²ò¤¬¤Ê¤¤¤«Ãµ¤¹¡Û
			¾¯¤·¤Ç¤â¤è¤¤²ò¤ò¸«¤Ä¤±¤ë¤¿¤á¤Ë¡¢²ò¤ò1¤Ä¸«¤Ä¤±¤¿¤é¤½¤Î²ò¤ËɬÍפʥ¿¡¼¥ó¿ô¤ò¾å¸Â¤È¤·¤ÆÃµº÷¤ò³¤±¤Þ¤¹¡£
			Ä´¤Ù¤¿¾õÂ֤οô¤¬°ìÄê¿ô¤Ë㤷¤¿»þÅÀ¤Çõº÷¤ò½ªÎ»¤·¡¢¤½¤ì¤Þ¤Ç¤Ë¸«¤Ä¤±¤¿ºÇÎɤβò¤òºÎÍѤ·¤Þ¤¹¡£

		¡Ú6. õº÷»þ¤Ë¤³¤ì°Ê¾åõº÷¤·¤Æ¤â̵Â̤À¤È¤ï¤«¤Ã¤¿¾ì¹ç¤ä¥´¡¼¥ë¤·¤¿¾ì¹ç¤Ë¡¢¿ô¥¿¡¼¥óÁ°¤ËÌá¤ë¡Û
			ÉáÄÌ¡¢¥Ð¥Ã¥¯¥È¥é¥Ã¥¯Ë¡¤Ê¤É¤Îõº÷¤Ç¤Ï°ì¤ÄÁ°¤Î¾õÂÖ¤ËÌá¤êõº÷¤ò¤ä¤êľ¤·¤Þ¤¹¡£
			¤·¤«¤·¡¢¤³¤ÎÌäÂê¤Ç¤Ï1¤ÄÁ°¤ËÌá¤Ã¤¿¤È¤³¤í¤Ç1¥¿¡¼¥ó¸å¤ËÅþ㤹¤ë°ÌÃÖ¤ÏÂ礭¤¯ÊѲ½¤»¤º¡¢Æ±¤¸°ÌÃÖ¤ËÅþ㤹¤ë
			¥ë¡¼¥È¤Ï1¤Ä¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£¤½¤³¤Ç¡¢¾õÂÖ¤òÌ᤹¤È¤­¤Ë1¥¿¡¼¥óÁ°¤Ç¤Ï¤Ê¤¯°ìµ¤¤Ë¿ô¥¿¡¼¥óÁ°¤Î¾õÂ֤ˤޤÇ
			Ì᤹¤È¤¤¤¦Â绨ÇĤÊõº÷¤ò¤·¤Þ¤¹¡£¤³¤ì¤Ë¤è¤êõº÷·ë²Ì¤Î¼Á¤ò¤¢¤Þ¤êÍî¤È¤¹¤³¤È¤Ê¤¯¡¢·×»»Î̤òÂ礭¤¯ºï¸º¤¹¤ë
			¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£
			¤³¤Î¤È¤­¡¢²¿¥¿¡¼¥óÁ°¤Ë¤Þ¤ÇÌ᤹¤«¤È¤¤¤¦¤Î¤Ï¡¢¥´¡¼¥ë¤ËÅþ㤷¤¿²ó¿ô¤Ë¤è¤Ã¤ÆÁý¤ä¤·¤Æ¤¤¤Þ¤¹¡£(¤Ä¤Þ¤ê¡¢
			¥´¡¼¥ë¤ËÅþ㤷¤¿²ó¿ô¤¬Â¿¤¤¤Û¤ÉÂ绨ÇĤÊõº÷¤ò¤¹¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡£)

		¡Ú7. ¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤Î¥¹¥­¥Ã¥×¡Û
			¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤Ï·ê¤¬¤¢¤Ã¤Æ¼ÙËâ¤Ê¤È¤­¤Ë±ª²ó¤¹¤ë¥ë¡¼¥È¤òÄ̤뤿¤á¤ËÍѰդ·¤¿¤â¤Î¤Ê¤Î¤Ç¡¢¤â¤·¼¡¤Î¼¡¤Î
			¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤È¸½ºß¤Î¥Ü¡¼¥ë¤Î°ÌÃ֤δ֤˷꤬¤Ê¤±¤ì¤Ð¡¢¤â¤¦¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤ò̵»ë¤·¤Æ¡¢¼¡¤Î¼¡¤Î
			¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤òÌܻؤ¹¤è¤¦¤Ë¤·¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢Ä̤é¤Ê¤¯¤Æ¤â¤è¤¯¤Ê¤Ã¤¿¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤ò¤ï¤¶¤ï¤¶
			Ä̲᤹¤ë¤è¤¦¤Ê̵Â̤¬¸º¤ê¤Þ¤¹¡£

		¡Ú8. ¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤È¸½ºß¤Î¥Ü¡¼¥ë¤Î°ÌÃ֤δ֤˥¸¥ã¥ó¥×¤Ç¤­¤Ê¤¤¤Û¤É¤Î·ê¤¬¤¢¤ì¤ÐÁ°¤Î¾õÂÖ¤ËÌá¤ë¡Û
			¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤Î´Ö¤Ë¤ÏËÜÍ襸¥ã¥ó¥×¤Ç¤­¤Ê¤¤¤Û¤É¤Î·ê¤¬Â¸ºß¤¹¤ë¤³¤È¤Ï¤¢¤ê¤Þ¤»¤ó¤¬¡¢Â®ÅÙ¤òÍî¤È¤µ
			¤Ê¤¤¤è¤¦¤Ë¶Ê¤¬¤í¤¦¤È¤·¤Æ¤¤¤ë¤ÈÊѤʾì½ê¤ËÆþ¤ê¹þ¤ó¤Ç¤·¤Þ¤¤¡¢¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤È¸½ºß¤Î¥Ü¡¼¥ë¤Î°ÌÃ֤δ֤Ë
			¥¸¥ã¥ó¥×¤Ç¤­¤Ê¤¤·ê¤¬Â¸ºß¤¹¤ë¤³¤È¤¬¤¢¤ê¤Þ¤¹¡£¤³¤ì¤ò±ª²ó¤·¤è¤¦¤Èõº÷¤·¤Æ¤¤¤ë¤ÈÈó¾ï¤Ë·×»»¥³¥¹¥È¤¬¤«¤«¤ë¤¿¤á
			¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤È¸½ºß¤Î¥Ü¡¼¥ë¤Î°ÌÃ֤δ֤˥¸¥ã¥ó¥×¤Ç¤­¤Ê¤¤·ê¤¬¤¢¤Ã¤¿¾ì¹ç¡¢¤½¤³¤ÇÄü¤á¤Æ¿ô¥¿¡¼¥óÁ°¤Î¾õÂÖ¤Þ¤Ç
			Ìᤷ¤Æ¤·¤Þ¤¤¤Þ¤¹¡£


*/
#include "common.hpp"
#include "answer.hpp"


//**********************************************************************************************//
//*     Äê¿ôÄêµÁ¤ä´Ê°×´Ø¿ôÄêµÁ¡¢¥°¥í¡¼¥Ð¥ëÊÑ¿ôÄêµÁ¤Ê¤É
//**********************************************************************************************//

// ¥Ç¥Ð¥Ã¥°ÍѤÎinclude¤ä´Ø¿ôÄêµÁ
#ifdef DEBUG
#	include <algorithm>
#	include <limits>

bool fIsValid(const float aValue) {
	if (-std::numeric_limits<float>::max() <= aValue &&
	  aValue <= std::numeric_limits<float>::max()) {
		return true;
	} else {
		return false;
	}
}

#endif

// ¥Ç¥Ð¥Ã¥°ÍѤβèÁü¤Î¤¿¤á¤Î¥Ç¡¼¥¿¤ò½ÐÎϤ¹¤ë¥Þ¥¯¥í
#ifndef IMG_DATA_PRINT
#	define IMG_DATA_PRINT(...)
#endif

// ¥¿¥¤¥à¥¢¥¦¥È»þ¤Ë¥¨¥é¡¼¤Ë¤µ¤»¤¿¤¤¾ì¹ç¤Ë¤Ï¡¢¤³¤Îdefine¤òÍ­¸ú¤Ë¤¹¤ë¡£
#define TIMEOUT_IS_ERROR

// ¥°¥í¡¼¥Ð¥ëÊÑ¿ô
static unsigned int gameIndex_ = 0;
static unsigned int turnIndex_ = 0;

// Äê¿ôÄêµÁ
#define LOOP_LIMIT 10000				// õº÷¤ÎÀ©¸Â
#define FLOAT_MAX (1.0f/0.0000000001f)	// float¤ÎºÇÂçÃ͡ڤȤꤢ¤¨¤º¡¢Â礭¤¤¤À¤±¤Î¿ôÃͤDZþµÞ½èÃÖ¡Û
#define DELTA (0.01f)					// ¶á˵¤Î°ÌÃÖ¤ò¼èÆÀ¤¹¤ë¤¿¤á¤Î¾®¤µ¤ÊÃÍ
#define MAX_NODE_COUNT  (((MAX_HOLE_COUNT * 4) + 5) * 3 )	// ¥À¥¤¥¯¥¹¥È¥é¤Ç°·¤¦¥Î¡¼¥É¤ÎºÇÂç¿ô

// ¥Ç¥Ð¥Ã¥°ÍѤβèÁü¤ÇÀþ¤òÉÁ²è¤¹¤ë¤Î¤Ë»È¤¦¿§(IMG_DATA_PRINT¥Þ¥¯¥í¤Î°ú¿ô¤Ç»È¤¦)
#define DEBUG_LINE_COLOR1 "44aa0000"
#define DEBUG_LINE_COLOR2 "3333ffff"
#define DEBUG_LINE_COLOR3 "0033ff55"
#define DEBUG_LINE_COLOR4 "3333ff55"

// õº÷¤Ç°·¤¦¥¢¥¯¥·¥ç¥ó¤ÎÁªÂò»è
enum ACCEL_DIRECTION{
	ACCEL_FORWARD,
	ACCEL_RIGHT45,
	ACCEL_LEFT45,
	ACCEL_RIGHT,
	ACCEL_LEFT,
	ACCEL_BRAKE,	// ¥Ö¥ì¡¼¥­
	ACCEL_DIRECTION_MAX,
};

// ACCEL_DIRECTION¤Î¥Ù¥¯¥È¥ëɽ¸½¡Ê¥×¥í¥°¥é¥à¤Î½é´ü²½»þ¤Ënormalize¤µ¤ì¤ë¡Ë
static Vector2 ACCEL_VECTOR[ACCEL_DIRECTION_MAX-1] = {
	Vector2(1,  0), // ACCEL_FORWARD
	Vector2(1,  1), // ACCEL_RIGHT45
	Vector2(1, -1), // ACCEL_LEFT45
	Vector2(0,  1), // ACCEL_RIGHT
	Vector2(0, -1), // ACCEL_LEFT
	// ACCEL_BRAKE
};

// ³Ñ¤Î¼ïÎà
Rect::CornerKind CORNER_KINDS[] = {
	Rect::CornerKind_LeftUp,
	Rect::CornerKind_LeftDown,
	Rect::CornerKind_RightUp,
	Rect::CornerKind_RightDown
};

// 8Êý¸þ¤òɽ¤¹Äê¿ô
enum Direction8{
	Direction8_Up,
	Direction8_RightUp,
	Direction8_Right,
	Direction8_RightDown,
	Direction8_Down,
	Direction8_LeftDown,
	Direction8_Left,
	Direction8_LeftUp,
	Direction8_MAX
};

// 8Êý¸þ¤òɽ¤¹¥Ù¥¯¥È¥ë
static Vector2 DIRECTION8_VECTOR[Direction8_MAX] = {
	Vector2( 0, -1), // Direction8_Up,
	Vector2( 1, -1), // Direction8_RightUp,
	Vector2( 1,  0), // Direction8_Right,
	Vector2( 1,  1), // Direction8_RightDown,
	Vector2( 0,  1), // Direction8_Down,
	Vector2(-1,  1), // Direction8_LeftDown,
	Vector2(-1,  0), // Direction8_Left,
	Vector2(-1, -1)  // Direction8_LeftUp,
};

// 4Êý¸þ¤òɽ¤¹Äê¿ô
enum Direction4{
	Direction4_Up,
	Direction4_Right,
	Direction4_Down,
	Direction4_Left,
	Direction4_MAX
};

// 4Êý¸þ¤òɽ¤¹¥Ù¥¯¥È¥ë
static Vector2 DIRECTION4_VECTOR[Direction4_MAX] = {
	Vector2( 0, -1), // Direction8_Up,
	Vector2( 1,  0), // Direction8_Right,
	Vector2( 0,  1), // Direction8_Down,
	Vector2(-1,  0), // Direction8_Left,
};

// ´Ê°×´Ø¿ôÄêµÁ
#define ABS(a)   ((a < 0)? -(a): (a))
#define MAX(a, b)   ((a < b)? b: a)
#define MIN(a, b)   ((a < b)? a: b)

// float¤ÎÈæ³Ó´Ø¿ô
bool Equal(float a, float b, float tolerance = 0.01){
	float d = ABS(a - b);
	return d < tolerance;
}

template <typename TYPE>
void swap(TYPE &a, TYPE &b){
	TYPE t = a;
	a = b;
	b = t;
}

// value¤¬left¤Èright¤Î´Ö¤Ë¤¢¤ëÃͤ«¤É¤¦¤«È½Äꤹ¤ë´Ø¿ô
bool Between(float left, float value, float right, bool border = true){
	if(left > right){
		swap(left, right);
	}
	if(border){
		return left <= value && value <= right;
	}
	else{
		return left < value && value < right;
	}
}

//**********************************************************************************************//
//*     ¥Ù¥¯¥È¥ë±é»»·Ï¤Î´Ø¿ô
//**********************************************************************************************//

//=============================================================================================//
//     ¥Ù¥¯¥È¥ë¤ÎÊý¸þ¤¬Æ±¤¸¤«¤É¤¦¤«È½Äê
//=============================================================================================//
bool EqualDirection(Vector2 a, Vector2 b){
	if(Equal(a.getLength(), 0.0f)){
		return Equal(b.getLength(), 0.0f);
	}
	else if(Equal(b.getLength(), 0.0f)){
		return false;
	}
	a.normalize();
	b.normalize();
	return Equal(a.x, b.x) && Equal(a.y, b.y);
}

//=============================================================================================//
//     Æó¤Ä¤Î¥Ù¥¯¥È¥ë¤Î¤Ê¤¹³Ñ(cos¦È)¤òµá¤á¤ë
//=============================================================================================//
float Cos(const Vector2 &v1, const Vector2 &v2){
	HAL_ASSERT(v1.getLength() * v2.getLength() > 0);
	return v1.getDotProduct(v2) / (v1.getLength() * v2.getLength());
}

//=============================================================================================//
//     Vector2¤òDirection8¤ËÊÑ´¹
//=============================================================================================//
Direction8 VectorToDirection8(const Vector2 &v){
	// v¤È°ìÈֶᤤDirection8¤Î¥Ù¥¯¥È¥ë¤ò¸«¤Ä¤±¤Æ¤½¤ì¤òºÎÍÑ
	Direction8 best;
	float best_score = -1;
	for(int i=0; i<Direction8_MAX; ++i){
		float score = v.getDotProduct(DIRECTION8_VECTOR[i]) / (v.getLength() * DIRECTION8_VECTOR[i].getLength());
		if(score > best_score){
			best_score = score;
			best = (Direction8)i;
		}
	}

	return best;
}

//=============================================================================================//
//     Vector2¤òDirection4¤ËÊÑ´¹
//=============================================================================================//
Direction4 VectorToDirection4(const Vector2 &v){
	// v¤È°ìÈֶᤤDirection4¤Î¥Ù¥¯¥È¥ë¤ò¸«¤Ä¤±¤Æ¤½¤ì¤òºÎÍÑ
	Direction4 best;
	float best_score = -1;
	for(int i=0; i<Direction4_MAX; ++i){
		float score = v.getDotProduct(DIRECTION4_VECTOR[i]) / (v.getLength() * DIRECTION4_VECTOR[i].getLength());
		if(score > best_score){
			best_score = score;
			best = (Direction4)i;
		}
	}

	return best;
}

//=============================================================================================//
//     base¤«¤é¸«¤Æv¤¬±¦¤Ë¤¢¤ë¤«¤É¤¦¤«È½Äê
//=============================================================================================//
bool isRight(Vector2 base, Vector2 v){
	base.normalize();
	float sin = base.y, cos = base.x;
	v = Vector2(v.x * cos + v.y * sin, -v.x * sin + v.y * cos);
	return v.y > 0;
}

// std::pair¤ÎÂåÂØ¡Úºî¤Ã¤¿¤±¤É»È¤Ã¤Æ¤Ê¤¤¡£¾Ã¤·Ëº¤ì¡£¡Û
template<class C1, class C2>
struct pair{
	C1 first;
	C2 second;

	pair(){}
	pair(const C1 &first, const C2 &second): first(first), second(second){}
};

//**********************************************************************************************//
//*     ľÀþ¤ä¶ë·Á¤Î¸òº¹È½Äê¤ä¸òÅÀ¤òµá¤á¤ë´Ø¿ô¤Ê¤É
//**********************************************************************************************//

//=============================================================================================//
//     Àþʬ¤Î¸òÅÀ¤ò¼èÆÀ
//=============================================================================================//
bool CrossPoint(const Vector2 &s1, const Vector2 &e1, const Vector2 &s2, const Vector2 &e2, Vector2 *c, bool border = true){
	// ¡Ú¤â¤Ã¤È¤Á¤ã¤ó¤È¤·¤¿µá¤áÊý¤¬¤¢¤ë¤È»×¤¦¤±¤É¡¢¤È¤ê¤¢¤¨¤º¤³¤ì¤Ç±þµÞ½èÃÖ¡Û
	Vector2 d1 = e1 - s1,
			d2 = e2 - s2;
	if(d1.y == 0 && d2.y != 0 && d1.x != 0 && d2.x == 0){
		// ľÀþ(e1 - s1)¤¬¿åÊ¿¡¢Ä¾Àþ(e2 - s2)¤¬¿âľ¤Ê¾ì¹ç
		(*c).x = s2.x;
		(*c).y = s1.y;
		return Between(s1.x, (*c).x, e1.x, border) && Between(s2.y, (*c).y, e2.y, border);
	}
	else if(d1.y != 0 && d2.y == 0 && d1.x == 0 && d2.x != 0){
		// ľÀþ(e1 - s1)¤¬¿âľ¡¢Ä¾Àþ(e2 - s2)¤¬¿åÊ¿¤Ê¾ì¹ç
		(*c).x = s1.x;
		(*c).y = s2.y;
		return Between(s1.y, (*c).y, e1.y, border) && Between(s2.x, (*c).x, e2.x, border);
	}
	else if(d1.y * d2.x == d2.y * d1.x){// ·¹¤­¤¬Æ±¤¸
		return false;	// ʹÔ
	}
	else{
		// ľÀþ1¤Î¼°¡§ y = (d1.y / d1.x) * x + a1
		float a1 = s1.y - (d1.y / d1.x) * s1.x,
			  a2 = s2.y - (d2.y / d2.x) * s2.x;

		if(d1.x == 0){
			// ľÀþ(e1 - s1)¤¬¿âľ
			(*c).x = s1.x;
			(*c).y = (d2.y / d2.x) * (*c).x + a2;
		}
		else if(d2.x == 0){
			// ľÀþ(e2 - s2)¤¬¿âľ
			(*c).x = s2.x;
			(*c).y = (d1.y / d1.x) * (*c).x + a1;
		}
		else{
			// ¸òÅÀ¤Î¼°¡§ (d1.y / d1.x) * x + a1 = (d2.y / d2.x) * x + a2
			//         ¡§ x = (a2 - a1) / ((d1.y / d1.x) - (d2.y / d2.x))
			(*c).x = (a2 - a1) / ((d1.y / d1.x) - (d2.y / d2.x));
			(*c).y = (d1.y / d1.x) * (*c).x + a1;
		}
		// Àþʬ¤ÎÈÏ°ÏÆâ¤«¤É¤¦¤«È½Äê
		return ((Equal(s1.x, e1.x) && Equal(s1.x, (*c).x)) || Between(s1.x, (*c).x, e1.x, border)) &&
			   ((Equal(s1.y, e1.y) && Equal(s1.y, (*c).y)) || Between(s1.y, (*c).y, e1.y, border)) &&
			   ((Equal(s2.x, e2.x) && Equal(s2.x, (*c).x)) || Between(s2.x, (*c).x, e2.x, border)) &&
			   ((Equal(s2.y, e2.y) && Equal(s2.y, (*c).y)) || Between(s2.y, (*c).y, e2.y, border));
	}
}

//=============================================================================================//
//     ľÀþ¤È¶ë·Á¤Î¸ò¤ï¤ëŤµ¤ò¼èÆÀ
//=============================================================================================//
bool CrossLength(const Vector2 &start, const Vector2 &end, const Rect &rect, float *length){
	// ¡Ú¶­³¦¤Ç¸ò¤ï¤ë¤È¥Ð¥°¤¬½Ð¤½¤¦¤À¤±¤É¡¢¤È¤ê¤¢¤¨¤ºÊüÃÖ¡Û
	// ¡Ú¶ë·Á¤ÎÃæ¤ËľÀþ¤¬Æþ¤Ã¤¿¾ì¹ç¤Ë¸òº¹¤·¤¿¤ÈȽÄꤵ¤ì¤Ê¤¤¡Û
	// rect¤Î4ľÀþ¤ÈľÀþ(end- start)¤Î¸òÅÀ¤òµá¤á¤ë
	Vector2 cross[2];
	int cross_count = 0;
	int size = sizeof(CORNER_KINDS)/sizeof(Rect::CornerKind);
	for(int k=0; k<size; ++k){
		if(CrossPoint(start, end, rect.getCornerPos((Rect::CornerKind)k), rect.getCornerPos((Rect::CornerKind)((k+1) % size)), &cross[cross_count])){
			++cross_count;
			if(cross_count == 2){
				break;
			}
		}
	}
	// 2²Õ½ê¤Î¸òÅÀ¤¬¤¢¤ì¤Ð¤½¤Î¸òÅÀ¤ò·ë¤ÖľÀþ¤ÎŤµ¤¬¡¢Ä¾Àþ¤È¶ë·Á¤Î¸ò¤ï¤ëŤµ
	if(cross_count == 2){
		(*length) = (cross[0] - cross[1]).getLength();
		return true;
	}
	return false;
}

//=============================================================================================//
//     ¶ë·ÁƱ»Î¤Î¸òÅÀ¤òµá¤á¤ë
//=============================================================================================//
bool CrossPoint(const Rect &r1, const Rect &r2, Vector2 points[4], int *point_count){
	// 2¤Ä¤Î¶ë·Á¤Î4¤Ä¤ÎľÀþ¤ÎÁ´¤Æ¤ÎÁȤǸòº¹È½Äê¤ò¹Ô¤¦
	int corner_kind_count = Rect::CornerKind_End_ - Rect::CornerKind_Begin_;
	(*point_count) = 0;
	Vector2 pos;
	for(int i=0; i<corner_kind_count; ++i){
		for(int j=0; j<corner_kind_count; ++j){
			if(CrossPoint(
				r1.getCornerPos((Rect::CornerKind)i), r1.getCornerPos((Rect::CornerKind)((i+1)%corner_kind_count)),
				r2.getCornerPos((Rect::CornerKind)j), r2.getCornerPos((Rect::CornerKind)((j+1)%corner_kind_count)),
				&pos, false
				)){
					points[(*point_count)++] = pos;
			}
		}
	}
	HAL_ASSERT((*point_count) <= 4);
	return (*point_count) != 0;
}

//=============================================================================================//
//     ľÀþ¤¬·ê¤È¸ò¤ï¤ë¤«È½Äê(¤¿¤À¤·¡¢jump == true¤Î¤È¤­¥¸¥ã¥ó¥×²Äǽ¤Ê¤â¤Î¤Ï̵»ë)
//=============================================================================================//
bool isCrossHole(const Field& aField, const Vector2 &a, const Vector2 &b, const bool jump = true, const float limit = MAX_VEL){
	// ¡Ú2¤Ä°Ê¾å¤Î·ê¤¬´Ø·¸¤¹¤ëÆÃ¼ì¤Ê¥±¡¼¥¹¤Ç¥Ð¥°¤¬¤Ç¤ë¤±¤É¡¢¤È¤ê¤¢¤¨¤ºÊüÃÖ¡Û
	float length;
	for(int i=0; i<aField.getHoleCount(); ++i){
		if(aField.getHole(i).isIntersectWithLineSegment(a, b)){
			// jump¥Õ¥é¥°¤¬true¤Î¤È¤­¤Ï¡¢¥¸¥ã¥ó¥×²Äǽ¤Ê¤é¸òº¹¤·¤Æ¤¤¤Ê¤¤¤ÈȽÄꤹ¤ë
			if(jump && CrossLength(a, b, aField.getHole(i), &length)){
				if(length < limit){
					continue;	// ¥¸¥ã¥ó¥×²Äǽ(¥Ü¡¼¥ë¤Î®Å٤ʤɤϹÍθ¤·¤Æ¤¤¤Ê¤¤¤Î¤Ç¥¸¥ã¥ó¥×¤Ç¤­¤Ê¤¤¤³¤È¤â¤¢¤ë)
				}
			}
			return true;
		}
	}
	return false;
}

//**********************************************************************************************//
//*     À¸À®¤·¤¿¥ë¡¼¥È¤Ë±è¤Ã¤ÆÁö¤ë¥¢¥¯¥·¥ç¥ó¤ÎºîÀ®
//**********************************************************************************************//

//=============================================================================================//
//     ¸½ºß¤Îstatus¤«¤étarget¥Ù¥¯¥È¥ë¤ÎÊý¸þ¤Ë®ÅÙ¤òÊѹ¹¤¹¤ë¤Î¤ËɬÍפʵ÷Î¥¤òµá¤á¤ë
//=============================================================================================//
Vector2 GetChangeVector(Status status, const Vector2 &target){
	if(Equal(status.getBallVel().getLength(), 0.0f)){
		return Vector2(0.0f, 0.0f);
	}

	Vector2 start = status.getBallPos();
	// status.getBallVel() ¤È target ¤Î´Ø·¸¤¬¡¢±¦¢ªº¸ or º¸¢ª±¦ ¤ËÊѲ½¤¹¤ë¤Þ¤Ç°Üư¤µ¤»¤Æ¤ß¤ë
	if(isRight(status.getBallVel(), target)){
		do{
			status.update(Action(Vector2(-status.getBallVel().y, status.getBallVel().x)));
		}while(isRight(status.getBallVel(), target));	// ¡ÚÀµ³Î¤Ë¤Ï±¦¢ªº¸¤Ë¤Ê¤ë¤Þ¤Ç¤Ç¤Ï¤Ê¤¯°ìÃפ¹¤ë¤Þ¤Ç¤À¤±¤É¡¢¤È¤ê¤¢¤¨¤º¤³¤ì¤Ç±þµÞ½èÃÖ¡Û
	}
	else{
		do{
			status.update(Action(Vector2(status.getBallVel().y, -status.getBallVel().x)));
		}while(!isRight(status.getBallVel(), target));
	}

	return status.getBallPos() - start;
}

//=============================================================================================//
//     ºÂɸ¤«¤é³Ñ¤Î¼ïÎà(±¦²¼¡¢º¸¾å¤Ê¤É)¤òÆÃÄê
//=============================================================================================//
Rect::CornerKind GetCornerType(const Field& aField, const Vector2 &v1, const Vector2 &v2){
	Rect::CornerKind kind = Rect::CornerKind_End_;
	bool right = isRight(v1, v2);
	Direction4 d;
	switch(VectorToDirection8(v1)){
		// ¾å²¼º¸±¦¤Ï¤½¤Î¤Þ¤Þ4Êý¸þ¤Î¾å²¼º¸±¦¤ØÊÑ´¹
		case Direction8_Up:			d = Direction4_Up;		break;
		case Direction8_Right:		d = Direction4_Right;	break;
		case Direction8_Down:		d = Direction4_Down;	break;
		case Direction8_Left:		d = Direction4_Left;	break;
		// ¼Ð¤á¤ÎÊý¸þ¤À¤Ã¤¿¾ì¹ç¡¢v2¤ÎÃͤ«¤éȽÃÇ
		case Direction8_RightUp:
			switch(VectorToDirection8(v2)){
				case Direction8_Up:		d = Direction4_Right; break;
				case Direction4_Right:	d = Direction4_Up; break;
				default:  d = (right)? Direction4_Up: Direction4_Right; break;
			}
			break;
		case Direction8_RightDown:
			switch(VectorToDirection8(v2)){
				case Direction8_Down:	d = Direction4_Right; break;
				case Direction4_Right:	d = Direction4_Down; break;
				default:  d = (right)? Direction4_Right: Direction4_Down; break;
			}
			break;
		case Direction8_LeftDown:
			switch(VectorToDirection8(v2)){
				case Direction8_Down:	d = Direction4_Left; break;
				case Direction4_Left:	d = Direction4_Down; break;
				default:  d = (right)? Direction4_Down: Direction4_Left; break;
			}
			break;
		case Direction8_LeftUp:
			switch(VectorToDirection8(v2)){
				case Direction4_Up:		d = Direction4_Left; break;
				case Direction4_Left:	d = Direction4_Up; break;
				default:  d = (right)? Direction4_Left: Direction4_Up; break;
			}
			break;
	}
	// °ÜưÊý¸þd¤«¤é³Ñ¤Î¼ïÎàkind¤ØÊÑ´¹
	switch(d){
		case Direction4_Down:	kind = (right)? Rect::CornerKind_RightDown:	Rect::CornerKind_LeftDown;	break;
		case Direction4_Up:		kind = (right)? Rect::CornerKind_LeftUp:	Rect::CornerKind_RightUp;	break;
		case Direction4_Left:	kind = (right)? Rect::CornerKind_LeftDown:	Rect::CornerKind_LeftUp;	break;
		case Direction4_Right:	kind = (right)? Rect::CornerKind_RightUp:	Rect::CornerKind_RightDown;	break;
	}
	return kind;
}

//=============================================================================================//
//     ·ê¤ËÍî¤Á¤ë¤«¤É¤¦¤«È½Äê¡Ê¤¿¤À¤·¡¢¥Õ¥£¡¼¥ë¥ÉÁ´ÂΤ˼ý¤Þ¤Ã¤Æ¤¤¤ë¤«¤É¤¦¤«¤Ïµ¤¤Ë¤·¤Ê¤¤¡Ë
//=============================================================================================//
bool isInHole2(const Field &aField, const Vector2& aBallPos, const Vector2 &target, const Vector2 &corner_pos, const bool left) {
    // Á´¤Æ¤Î·ê¤Î¥Á¥§¥Ã¥¯
	for (int idx = 0; idx < aField.getHoleCount(); ++idx) {
        const Rect& rect = aField.getHole(idx);
		if (rect.isInWithBorder(aBallPos)){
			Vector2 v = rect.getCenterPos() - corner_pos;
			bool f = isRight(target, v);
			if((f && !left) || (!f && left)){
				return true;
			}
		}
    }
    return false;
}

//=============================================================================================//
//     next_targetÊý¸þ¤Ë¶Ê¤¬¤Ã¤Æ¤¤¤¤¤«¥Á¥§¥Ã¥¯¤¹¤ë
//=============================================================================================//
float CurveCheck(const Field &aField, Status status, const Vector2 &target, const Vector2 &corner_pos, const bool left){
	if(Equal(status.getBallVel().getLength(), 0.0f)){
		return true;
	}

	float all_length = 0.0f,	// ¡Ṳ́»ÈÍÑ¡Û
		  hole_length = 0.0f,	// ¤³¤Î¤Þ¤Þ¶Ê¤¬¤Ã¤¿¤È¤­¤Ë¤É¤ì¤À¤±·ê¤Î¾å¤òÁö¤ë¤³¤È¤Ë¤Ê¤ë¤Î¤«¤È¤¤¤¦¤À¤¤¤¿¤¤¤Îµ÷Î¥
		  length;
	Vector2 old_pos;
	// status.getBallVel() ¤È target ¤Î´Ø·¸¤¬¡¢±¦¢ªº¸ or º¸¢ª±¦ ¤ËÊѲ½¤¹¤ë¤Þ¤Ç°Üư¤µ¤»¤ë
	if(isRight(status.getBallVel(), target)){
		do{
			old_pos = status.getBallPos();
			status.update(Action(Vector2(-status.getBallVel().y, status.getBallVel().x)));
			length = (status.getBallPos() - old_pos).getLength();
			all_length += length;	// ¡Ṳ́»ÈÍÑ¡Û
			// ·ê¤ÎÃæ¢ª·ê¤ÎÃæ¤Ø¤Î°Üư¤ò¤·¤Æ¤¤¤ë¤È¤­hole_length¤Ë°Üưµ÷Î¥¤ò²Ã»»
			if(isInHole2(aField, old_pos, target, corner_pos, left) && isInHole2(aField, status.getBallPos(), target, corner_pos, left)){
				hole_length += length;
			}
			// ¡Ú¥Ç¥Ð¥Ã¥°ÍѽÐÎÏ¡Û
			IMG_DATA_PRINT("%f %f %f %f %s\n", old_pos.x, old_pos.y, status.getBallPos().x, status.getBallPos().y, DEBUG_LINE_COLOR4);
		}while(isRight(status.getBallVel(), target));	// ¡ÚÀµ³Î¤Ë¤Ï±¦¢ªº¸¤Ë¤Ê¤ë¤Þ¤Ç¤Ç¤Ï¤Ê¤¯°ìÃפ¹¤ë¤Þ¤Ç¤À¤±¤É¡¢¤È¤ê¤¢¤¨¤º¤³¤ì¤Ç±þµÞ½èÃÖ¡Û
	}
	else{
		do{
			old_pos = status.getBallPos();
			status.update(Action(Vector2(status.getBallVel().y, -status.getBallVel().x)));
			length = (status.getBallPos() - old_pos).getLength();
			all_length += length;	// ¡Ṳ́»ÈÍÑ¡Û
			// ·ê¤ÎÃæ¢ª·ê¤ÎÃæ¤Ø¤Î°Üư¤ò¤·¤Æ¤¤¤ë¤È¤­hole_length¤Ë°Üưµ÷Î¥¤ò²Ã»»
			if(isInHole2(aField, old_pos, target, corner_pos, left) && isInHole2(aField, status.getBallPos(), target, corner_pos, left)){
				hole_length += length;
			}
			// ¡Ú¥Ç¥Ð¥Ã¥°ÍѽÐÎÏ¡Û
			IMG_DATA_PRINT("%f %f %f %f %s\n", old_pos.x, old_pos.y, status.getBallPos().x, status.getBallPos().y, DEBUG_LINE_COLOR4);
		}while(!isRight(status.getBallVel(), target));
	}

	return hole_length;
}

//=============================================================================================//
//     ID¤òVector2¤ËÊÑ´¹¤¹¤ë(GetEstimatedBestActionVector´Ø¿ô¤Ç¤Î¤ß»ÈÍÑ)
//=============================================================================================//
Vector2 FToVector(
	const Field &aField, int f, const Status &status, const bool left,
	Vector2 target, const Vector2 &next_target, const Vector2 &v, Rect::CornerKind corner_kind, float curve_angle,
	const Vector2 &corner_pos
){
	Vector2 result;
	f = (f + 4*100) % 4;	// f¤ò0¡Á3¤ÎÈϰϤ˼ý¤á¤ë¡Úf<-400¤À¤È¤ª¤«¤·¤¯¤Ê¤ë¤±¤É¤½¤ó¤Ê¤³¤È¤Ï¤¿¤Ö¤ó¤Ê¤¤¤Î¤Ç¡¢¤È¤ê¤¢¤¨¤º¤³¤ì¤Ç±þµÞ½èÃÖ¡Û
	if(f == 0){
		// CurveCheck¤Î·ë²Ì¼¡Âè¤Çf¤ò½¤Àµ
		float hole_length = CurveCheck(aField, status, next_target, corner_pos, left);
		if(Equal(hole_length, 0.0f)){
			f = f;
		}
		else if(hole_length < status.getBallVel().getLength() * 2){
			f = 3;
		}
		else{
			f = 2;
		}
	}
	else if(f == 3){
		// CurveCheck¤Î·ë²Ì¼¡Âè¤Çf¤ò½¤Àµ
		float hole_length = CurveCheck(aField, status, next_target, corner_pos, left);
		if(Equal(hole_length, 0.0f)){
			f = f;
		}
		else if(hole_length < status.getBallVel().getLength() * 2){
			f = 3;
		}
		else{
			f = 2;
		}
	}
	switch(f){
		case 0:
			// next_targetÊý¸þ¤Ø¶Ê¤¬¤ë
			result = (!left)? Vector2(-status.getBallVel().y, status.getBallVel().x): Vector2(status.getBallVel().y, -status.getBallVel().x);
			break;
		case 2:
			// next_targetÊý¸þ¤È¤ÏµÕÊý¸þ¤Ø
			result = (left)? Vector2(-status.getBallVel().y, status.getBallVel().x): Vector2(status.getBallVel().y, -status.getBallVel().x);
			{
				// v¤¬Ä¹¤¤¤Û¤ÉtargetÊý¸þ¤Ø¥Ù¥¯¥È¥ë¤ò½¤Àµ¤¹¤ë
				float rate = 0.0f;
				for(int i=10; i!=1; --i){
					if(v.getLength() > MAX_VEL * i){
						rate = 0.25f * (i-1);
						break;
					}
				}
				if(!Equal(result.getLength(), 0.0f)){
					result.normalize();
					result += target.normalize() * rate;
				}
			}
			// curve_angle¤¬Â礭¤¤¤È¤­¤Ë¤âtargetÊý¸þ¤Ø¥Ù¥¯¥È¥ë¤ò½¤Àµ¤¹¤ë
			if(curve_angle > 0.0f){
				if(Equal(result.getLength(), 0.0f)){
					result = target;
				}
				else{
					float a = curve_angle;
					result = result.normalize() + target.normalize() * (6.0f * a * a * a * a);
				}
			}
			break;
		case 1:
			//*
			// ľ¿Ê
			switch(corner_kind){
				case Rect::CornerKind_RightUp:		result = (left)? Vector2( 0, -1): Vector2( 1,  0); break;
				case Rect::CornerKind_RightDown:	result = (left)? Vector2( 1,  0): Vector2( 0,  1); break;
				case Rect::CornerKind_LeftDown:		result = (left)? Vector2( 0,  1): Vector2(-1,  0); break;
				case Rect::CornerKind_LeftUp:		result = (left)? Vector2(-1,  0): Vector2( 0, -1); break;
			}
			// ¼ã´³¡¢targetÊý¸þ¤Ø¥Ù¥¯¥È¥ë¤ò½¤Àµ¤¹¤ë
			result = result.normalize() * 3 + target.normalize();
			/*/
			// targetÊý¸þ¤Ø¿¿¤Ãľ¤° + next_targetÊý¸þ¤È¤ÏµÕÊý¸þ¤Ø
			result = target * 3.0f + ((left)? Vector2(-status.getBallVel().y, status.getBallVel().x): Vector2(status.getBallVel().y, -status.getBallVel().x));
			//*/
			break;
		case 3:
			// next_targetÊý¸þ¤Ø¶Ê¤¬¤ë + ¸ºÂ® * 1.5
			result = (!left)? Vector2(-status.getBallVel().y, status.getBallVel().x): Vector2(status.getBallVel().y, -status.getBallVel().x);
			if(!Equal(result.getLength(), 0.0f)){
				result = result.normalize() * 1.5f + Vector2(-status.getBallVel().x, -status.getBallVel().y).normalize();
			}
			else{
				result = Vector2(-status.getBallVel().x, -status.getBallVel().y);
			}
			break;
	}
	return result;
}

//=============================================================================================//
//     ¼¡¤Ë¤¹¤ë¤ÈÎɤµ¤½¤¦¤Ê¹Ôư¤ò¿ä¬
//=============================================================================================//
Vector2 GetEstimatedBestActionVector(
	const Field& aField,
	const int target_point_id,
	const Vector2 check_points[MAX_NODE_COUNT],
	const int check_point_count,
	const Status &status
){
	Vector2 result;
	if(target_point_id == check_point_count-1){// ¼¡¤¬¥´¡¼¥ë¤Ê¤é¤Ð
		// vel¤ògoal¤Ë¶á¤Å¤±¤ë
		Vector2 vel = status.getBallVel(),
				goal = check_points[target_point_id] - status.getBallPos();
		if(Equal(vel.getLength(), 0.0f) || vel.getDotProduct(goal) / (vel.getLength()*goal.getLength()) >= 0.985f){
			result = goal;
		}
		else{
			// vel¤«¤é¸«¤Ægoal¤Ïº¸±¦¤É¤Á¤é¤Ë¤¢¤ë¤Î¤«¡©
			if(!isRight(vel, goal)){ // º¸
				result = Vector2(vel.y, -vel.x).changeLength(MAX_ACCEL);
				Vector2 new_vel = (vel + result);
				new_vel.changeLength(MAX_VEL);
				// ¶Ê¤ê¤¹¤®¤Ê¾ì¹ç¤Ë½¤Àµ
				if(isRight(new_vel, goal)){
					goal.changeLength(MAX_VEL);
					result = goal - vel;
				}
			}
			else{ // ±¦
				result = Vector2(-vel.y, vel.x).changeLength(MAX_ACCEL);
				Vector2 new_vel = (vel + result);
				new_vel.changeLength(MAX_VEL);
				// ¶Ê¤ê¤¹¤®¤Ê¾ì¹ç¤Ë½¤Àµ
				if(!isRight(new_vel, goal)){
					goal.changeLength(MAX_VEL);
					result = goal - vel;
				}
			}

			// goal¤È´Ø·¸¤Ê¤¤Êý¸þ¤Ø¤ÎÀª¤¤¤¬¶¯¤±¤ì¤Ð¤½¤ì¤òÂǤÁ¾Ã¤¹Êý¸þ¤Ë¥Ù¥¯¥È¥ë¤ò½¤Àµ(= ¤Á¤ç¤Ã¤È¥Ö¥ì¡¼¥­¤ò¤«¤±¤ë)
			result.normalize();
			float cos = Cos(vel, goal);
			float rate = 0.0f;
			for(int i=0; i<9; ++i){
				if(cos < -1.0f + i * 0.21f){
					rate = 2.9f - i * 0.3f;
					break;
				}
			}
			result = Vector2(-vel.x, -vel.y).normalize() * rate + result;
		}
		result.changeLength(MAX_ACCEL);
	}
	else{// ¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤¬¥´¡¼¥ë¤Ç¤Ê¤¤¾ì¹ç
		Vector2 target = check_points[target_point_id] - status.getBallPos(),
				next_target = check_points[target_point_id+1] - check_points[target_point_id];
		Vector2 change_vector = GetChangeVector(status, next_target);	// next_targetÊý¸þ¤Ë°ÜưÊý¸þ¤ò½¤Àµ¤¹¤ë¤Î¤ËɬÍ×¤Ê°ÜÆ°µ÷Î¥¤òµá¤á¤ë
		float curve_angle = Cos(target, next_target);

		// ¡Ú¥Ç¥Ð¥Ã¥°ÍѽÐÎÏ¡Û
		Vector2 p = status.getBallPos() + change_vector;
		IMG_DATA_PRINT("%f %f %f %f %s\n", status.getBallPos().x, status.getBallPos().y, p.x, p.y, DEBUG_LINE_COLOR3);

		// change_vector¤ä¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¡¢³Ñ¤Î¼ïÎà¤Ê¤É¤Î°ÌÃÖ´Ø·¸¤«¤é¼¡¤Î¹Ôư¤ÎÊý¿Ë¤ò·è¤á¤ë
		Vector2 start = check_points[target_point_id],
				end = status.getBallPos() + change_vector,
				v = end - start;
		bool left = !isRight(target, next_target);
		int f1 = -1;
		
		if(v.x > 0){
			if(v.y < 0){
				f1 = 0;
			}
			else{
				f1 = 3;
			}
		}
		else{
			if(v.y < 0){
				f1 = 1;
			}
			else{
				f1 = 2;
			}
		}
		
		Rect::CornerKind corner_kind = GetCornerType(aField, target, next_target);
		switch(corner_kind){
			case Rect::CornerKind_RightUp:		f1 = (!left)? f1+0: 3-(f1+3); break;
			case Rect::CornerKind_RightDown:	f1 = (!left)? f1+1: 3-(f1+0); break;
			case Rect::CornerKind_LeftDown:		f1 = (!left)? f1+2: 3-(f1+1); break;
			case Rect::CornerKind_LeftUp:		f1 = (!left)? f1+3: 3-(f1+2); break;
		}

		result = FToVector(aField, f1, status, left, target, next_target, v, corner_kind, curve_angle, check_points[target_point_id]);
		
		if(Equal(result.getLength(), 0.0f)){
			result = target;
		}
		else if(status.getBallVel().getLength() < MAX_VEL){
			// ®ÅÙ¤¬½½Ê¬¤Ç¤Ê¤±¤ì¤Ð¡¢ÌÜŪ¤ÎÊý¸þ(target)¤Ø¥Ù¥¯¥È¥ë¤ò¸þ¤±¤ë
			float rate = 0.1f;
			float length = status.getBallVel().getLength();
			for(int i=1, limit=6; i<limit; ++i){
				if(length < MAX_VEL * ((i < 4)? (1.0f / (5.0f-i)): ((i-2.0f)/(i-1.0f)))){
					rate = (limit - i) * 0.5f;
					break;
				}
			}
			result = result.normalize() + target.normalize() * rate;
		}
		// v¤¬Ã»¤±¤ì¤Ðnext_targetÊý¸þ¤Ë¶Ê¤¬¤ë¥Ù¥¯¥È¥ë¤ò²Ã¤¨¤ë
		/*if(v.getLength() < status.getBallVel().getLength()){
			result = result.normalize() + FToVector(0, status, left, target, v, corner_kind, curve_angle).normalize() * (4.5f * (status.getBallVel().getLength()/MAX_VEL) * (v.getLength() / status.getBallVel().getLength()));
		}*/
		result.changeLength(MAX_ACCEL);
	}

	return result;
}

//=============================================================================================//
//     ¥¢¥¯¥·¥ç¥ó¤ÎºîÀ®
//=============================================================================================//
// ¡Ú¤¤¤Ä¤âºÆµ¢´Ø¿ô¤Ç¼ÂÁõ¤¹¤ë¤ÈÃÙ¤¤¤Î¤Ç¥ë¡¼¥×¤Ç¼ÂÁõ¤·¤¿¤¬¡¢ËÜÅö¤ËÃÙ¤¤¤«¤É¤¦¤«¤Ï̤¸¡¾Ú¡Û
struct Stack{
	Action action;				// ÁªÂò¤µ¤ì¤¿¥¢¥¯¥·¥ç¥ó
	int i;						// ¥ë¡¼¥×ÊÑ¿ô
	Status status;				// ¸½ºß¤Î¥Ü¡¼¥ë¤Î°ÌÃÖ¤ä²Ã®Å٤Υ¹¥Æ¡¼¥¿¥¹
	int target_point_id;		// ¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤ÎID
	Vector2 estimated_vector;	// ¼¡¤Î¥¢¥¯¥·¥ç¥ó¤Ç²Ã®¤¹¤ë¤ÈÎɤµ¤½¤¦¤À¤È¿ä¬¤µ¤ì¤¿Êý¸þ¤Ø¤Î¥Ù¥¯¥È¥ë
	float distance_to_next;		// ¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤Þ¤Ç¤ÎľÀþµ÷Î¥
	float min_distance_to_goal;	// ¡Ṳ́»ÈÍÑ¡Û
};

int MakeActions(
	const Field& aField,
	const Vector2 check_points[MAX_NODE_COUNT],
	const int check_point_count,
	const bool jump,				// ¥¸¥ã¥ó¥×¤¢¤ê¤«¤Ê¤·¤«¤Î¥Õ¥é¥°
	int best_score,					// ¤³¤ì¤Þ¤Ç¤Ë¸«¤Ä¤±¤¿¥´¡¼¥ë¤¹¤ë¤Þ¤Ç¤ÎºÇû¤Î¥¿¡¼¥ó¿ô(¤³¤ì¤òͤ¨¤¿¤é¤½¤ì¤è¤êÀè¤Ïõº÷¤·¤Ê¤¤)
	Action actions[MAX_TURN_COUNT]	// õº÷¤Ç¸«¤Ä¤±¤¿¥Ù¥¹¥È¤Ê¥¢¥¯¥·¥ç¥ó¥ê¥¹¥È
){
	Stack stack[MAX_TURN_COUNT];
	int stack_count = 0;
	float limit_rate = best_score / 35.0f;	// ¥Ç¥Õ¥©¥ë¥È¤Î¥¢¥¯¥·¥ç¥ó¤Ç»þ´Ö¤Î¤«¤«¤ëÌäÂê¤Ç¤Ï¿¤¯Ãµº÷¤¹¤ë

	// stack¤Î½é´ü²½
	++stack_count;
	stack[stack_count-1].i = 0;
	stack[stack_count-1].status = Status(aField.getStartPos(), Vector2(0.0f, 0.0f));	// ½é´ü°ÌÃÖ
	stack[stack_count-1].target_point_id = 1;
	stack[stack_count-1].distance_to_next = (check_points[stack[stack_count-1].target_point_id] - stack[stack_count-1].status.getBallPos()).getLength();
	++stack_count;
	stack[stack_count-1].i = 0;
	stack[stack_count-1].target_point_id = stack[stack_count-2].target_point_id;
	stack[stack_count-1].status = stack[stack_count-2].status;
	stack[stack_count-1].estimated_vector = GetEstimatedBestActionVector(	// ¼¡¤Ë¤¹¤ë¤ÈÎɤµ¤½¤¦¤Ê¹Ôư¤ò¿ä¬
		aField, stack[stack_count-1].target_point_id, check_points, check_point_count, stack[stack_count-1].status
	);

	// ¡Ú¥Ç¥Ð¥Ã¥°ÍÑ¡Û
	IMG_DATA_PRINT("%f %f %f %f %s\n", stack[stack_count-2].status.getBallPos().x, stack[stack_count-2].status.getBallPos().y, stack[stack_count-1].status.getBallPos().x, stack[stack_count-1].status.getBallPos().y, DEBUG_LINE_COLOR2);

	int find = 0;
	Vector2 v1, v2;
	int next_target_id;
	int loop;
	for(loop=0; loop<LOOP_LIMIT*limit_rate; ++loop){
		Vector2 start = stack[stack_count-1].status.getBallPos(),
				end = check_points[stack[stack_count-1].target_point_id];
		Vector2 accel = stack[stack_count-1].estimated_vector;
		accel.changeLength(MAX_ACCEL);
		Vector2 ball_vel = stack[stack_count-1].status.getBallVel();

		// ¥¢¥¯¥·¥ç¥ó¤Î·èÄê
		float r2 = 1.0f / halSqrt(2.0f);
		if(stack[stack_count-1].i == ACCEL_BRAKE){
			// ¥Ö¥ì¡¼¥­ * 0.5 + estimated_vector
			Vector2 v = accel;
			if(!Equal(ball_vel.getLength(), 0.0f)){
				v = Vector2(-ball_vel.x, -ball_vel.y).normalize() * 0.5f + v.normalize();
			}
			v.changeLength(MAX_ACCEL);
			stack[stack_count-1].action = Action(v);
		}
		else{
			// estimated_vector¤ò0¡ë¡¢45¡ë¡¢90¡ëº¸±¦¤Ë²óž¤µ¤»¤¿¥Ù¥¯¥È¥ë¤ò¤½¤ì¤¾¤ì»î¤¹
			float cos = ACCEL_VECTOR[stack[stack_count-1].i].x,
				  sin = ACCEL_VECTOR[stack[stack_count-1].i].y;
			stack[stack_count-1].action = Action(Vector2(accel.x * cos - accel.y * sin, accel.x * sin + accel.y * cos));
		}

		// ¹Ôư
		stack[stack_count-1].status.update(stack[stack_count-1].action);
		stack[stack_count-1].distance_to_next = (check_points[stack[stack_count-1].target_point_id] - stack[stack_count-1].status.getBallPos()).getLength();
		HAL_ASSERT(fIsValid(stack[stack_count-1].status.getBallPos().x) && fIsValid(stack[stack_count-1].status.getBallPos().y));
		HAL_ASSERT(fIsValid(stack[stack_count-1].status.getBallVel().x) && fIsValid(stack[stack_count-1].status.getBallVel().y));

		// ¡Ú¥Ç¥Ð¥Ã¥°ÍѽÐÎÏ¡Û
		IMG_DATA_PRINT("%f %f %f %f %s\n", stack[stack_count-2].status.getBallPos().x, stack[stack_count-2].status.getBallPos().y, stack[stack_count-1].status.getBallPos().x, stack[stack_count-1].status.getBallPos().y, DEBUG_LINE_COLOR2);
		
		// ¥´¡¼¥ë¤·¤¿¤«È½Äê
		if(aField.isInGoal(stack[stack_count-2].status.getBallPos(), stack[stack_count-1].status.getBallPos())){
			// ¥Ù¥¹¥È¥¹¥³¥¢¤ò¹¹¿·
			best_score = stack_count-1;
			// ¥¢¥¯¥·¥ç¥ó¤ÎÊݸ
			for(int i=1; i<stack_count; ++i){
				actions[i-1] = stack[i].action;
			}
			++find;
			stack_count = MAX(stack_count - (10 + 5 * find), 3);	// ¤³¤ì¤Þ¤Ç¤Ë¥´¡¼¥ë¤·¤¿²ó¿ô¤Ë±þ¤¸¤Æstack¤òpop
			goto CANCEL;
			//return (find)? best_score: 0;	// ¡Ú¥Ç¥Ð¥Ã¥°ÍÑ¡Û
		}

		// target¤¬ÊѤï¤ë¤«È½Äê(¥Ù¥¯¥È¥ëv1¤Èv2¤Î¤Ê¤¹³Ñ¤¬90¡ë°Ê¾å¤Ë¤Ê¤Ã¤¿¤é¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥ÈÄ̲á¤ÈȽÄꤹ¤ë)
		next_target_id = stack[stack_count-1].target_point_id;
		do{
			v1 = check_points[next_target_id] - check_points[next_target_id-1],
			v2 = check_points[next_target_id] - stack[stack_count-1].status.getBallPos();
			if(!(v1.x * v2.x + v1.y * v2.y < 0)){
				break;
			}
			if(next_target_id+1 < check_point_count){
				++next_target_id;
			}
			else{
				goto CANCEL;
			}
		}while(1);
		// ¼¡¤Î¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤È¤Î´Ö¤Ë·ê¤¬¤Ê¤±¤ì¤Ð¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤ò¥¹¥­¥Ã¥×¤¹¤ë
		{
			int next_next_point_id = next_target_id+1;
			while(check_point_count > next_next_point_id && !isCrossHole(aField, stack[stack_count-1].status.getBallPos(), check_points[next_next_point_id], jump)){
				++next_target_id;
				++next_next_point_id;
			}
		}

		if(
				stack_count > best_score-1 ||// »þ´Ö¤«¤«¤ê¤¹¤®(¥Ù¥¹¥È¥¹¥³¥¢¤ò¹¹¿·¤¹¤ë¤³¤È¤¬¤Ê¤¤¤Î¤Ç¤³¤ì¤è¤êÀè¤Ïõº÷¤·¤Ê¤¤)
				isCrossHole(aField, stack[stack_count-1].status.getBallPos(), check_points[next_target_id]) ||// ¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤Þ¤Ç¤Î´Ö¤Ë·ê¤¬¤¢¤ë
				(
					stack_count >= 2 &&
					(stack[stack_count-2].target_point_id == next_target_id) &&
					stack[stack_count-2].distance_to_next <= stack[stack_count-1].distance_to_next
				) || // ¼¡¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤Þ¤Ç¤Îµ÷Î¥¤¬¸º¤Ã¤Æ¤Ê¤¤
				aField.isInHole(stack[stack_count-1].status.getBallPos())	// ·ê¤ËÍî¤Á¤¿
			){
			goto CANCEL;
		}
		else{// ¼¡¤Î¹Ôư¤Ø
			// ¥¹¥¿¥Ã¥¯¤òÀѤà
			++stack_count;
			stack[stack_count-1].i = 0;
			stack[stack_count-1].target_point_id = next_target_id;
			stack[stack_count-1].status = stack[stack_count-2].status;
			
			// ¼¡¤Ë¤¹¤ë¤ÈÎɤµ¤½¤¦¤Ê¹Ôư¤ò¿ä¬
			stack[stack_count-1].estimated_vector = GetEstimatedBestActionVector(
				aField, stack[stack_count-1].target_point_id, check_points, check_point_count, stack[stack_count-1].status
			);
			HAL_ASSERT(fIsValid(stack[stack_count-1].estimated_vector.x) && fIsValid(stack[stack_count-1].estimated_vector.y));
		}
		continue;
CANCEL:
		// ¹Ôư¤ò¥­¥ã¥ó¥»¥ë¤·¤Æ¼¡¤Ø
		while(stack[stack_count-1].i >= ACCEL_DIRECTION_MAX-1){
			// ¤³¤ì°Ê¾åpop¤Ç¤­¤Ê¤±¤ì¤Ðõº÷½ªÎ»
			if(stack_count == 2){
				stack_count = 0;	// ¡Ú¢«ÉÔÍפʥ³¡¼¥É¡£¾Ã¤·Ëº¤ì¡£¡Û
				goto END;
			}
			stack_count = MAX(stack_count - (1+find*3), 2);	// ¤³¤ì¤Þ¤Ç¤Ë¥´¡¼¥ë¤·¤¿²ó¿ô¤Ë±þ¤¸¤Æstack¤òpop
		}
		stack[stack_count-1].status = stack[stack_count-2].status;
		++stack[stack_count-1].i;
	}
END:;
	return (find)? best_score: 0;
}

//**********************************************************************************************//
//*     ¥À¥¤¥¯¥¹¥È¥é¤Ë¤è¤ë¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥ÈºîÀ® & ¥Ç¥Õ¥©¥ë¥È¤Î¥¢¥¯¥·¥ç¥óÀ¸À®
//**********************************************************************************************//

//=============================================================================================//
//     ¥Î¡¼¥É¥¯¥é¥¹(pos°Ê³°¤Ï¥Ç¥Ð¥Ã¥°ÍѤξðÊó¤òÊÝ»ý¤¹¤ë¤¿¤á¤Î¤â¤Î)
//=============================================================================================//
struct Node{
	Vector2 pos;
	int hole_id;	// ·ê¤ÎÈÖ¹æ¡Ú¥Ç¥Ð¥Ã¥°ÍÑ¡Û
	Rect::CornerKind corner;	// ³Ñ¤Î¼ïÎà¡Ú¥Ç¥Ð¥Ã¥°ÍÑ¡Û
	// ¥Î¡¼¥É¤Î¼ïÎà¡Ú¥Ç¥Ð¥Ã¥°ÍÑ¡Û
	enum Type{
		Type_Start,	// ¥¹¥¿¡¼¥ÈÃÏÅÀ¤Î¥Î¡¼¥É
		Type_Goal,	// ¥´¡¼¥ë¤Î¥Î¡¼¥É(¥´¡¼¥ë¤Ï¶ë·Á¤Ê¤Î¤Ç¡¢¤½¤Î»Í¶ù¤ÈÃæ¿´¤Î£µ¤Ä¤Î¥Î¡¼¥É¤¬Â¸ºß¤¹¤ë)
		Type_Corner,// ¤½¤ì¤¾¤ì¤Î·ê¤Î»Í¶ù¤Î¥Î¡¼¥É
		Type_Else	// ·ê¤È·ê¤Î¸òÅÀ¤Î¥Î¡¼¥É
	} type;

	Node(){}
	Node(const Vector2 &pos, const Type type): pos(pos), type(type){}
	Node(const Vector2 &pos, const int hole_id, const Rect::CornerKind corner): pos(pos), hole_id(hole_id), corner(corner), type(Type_Corner){}
};

//=============================================================================================//
//     ¥À¥¤¥¯¥¹¥È¥é ¥¯¥é¥¹(ÉáÄ̤ΥÀ¥¤¥¯¥¹¥È¥é¤È°ã¤¤¡¢¶Ê¤¬¤ë³ÑÅÙ¤ò¹Íθ¤·¤¿¥³¥¹¥È¤ò·×»»¤·¤Æ¤¤¤ë & ¥´¡¼¥ë¤¬Ê£¿ô)
//=============================================================================================//
class DijkstraAlgorithm{
public:
	typedef float COST_TYPE;
	
protected:
	COST_TYPE link_[MAX_NODE_COUNT][MAX_NODE_COUNT];	// ¥ê¥ó¥¯¾ðÊó(-1¤Ï̤Àܳ)
	Node *pos_list_;	// ¶Ê¤¬¤ë³ÑÅÙ¤ò¹Íθ¤·¤¿¥³¥¹¥È¤ò·×»»¤¹¤ë¤¿¤á¤Ë¤À¤±»ý¤Ã¤Æ¤¤¤ëĺÅÀºÂɸ
	float corner_rate_;	// ¶Ê¤¬¤ë³ÑÅÙ¤ò¹Íθ¤·¤¿¥³¥¹¥È¤Î¥ì¡¼¥È(¤³¤ì¤¬0¤À¤ÈÉáÄ̤ΥÀ¥¤¥¯¥¹¥È¥é¤ÈƱ¤¸)
public:
	// ¥³¥ó¥¹¥È¥é¥¯¥¿
	DijkstraAlgorithm(Node *pos_list, float corner_rate){
		// ½é´ü²½
		pos_list_ = pos_list;
		corner_rate_ = corner_rate;
		for(int i=0; i<MAX_NODE_COUNT; ++i){
			for(int j=0; j<MAX_NODE_COUNT; ++j){
				link_[i][j] = -1;
			}
		}
	}

	// ¥ê¥ó¥¯¤ÎÀßÄê
	void SetLink(const int node1, const int node2, const COST_TYPE &cost){
		link_[node1][node2] = cost;
		link_[node2][node1] = cost;
	}

	// ²ò¤¯
	float Solve(const int start_node, const int end_node[5], int best_root[MAX_NODE_COUNT]){
		float min_cost[MAX_NODE_COUNT];
		int prev_node[MAX_NODE_COUNT];
		bool expanded[MAX_NODE_COUNT];
		// ½é´ü²½
		for(int i=0; i<MAX_NODE_COUNT; ++i){
			min_cost[i] = FLOAT_MAX;
			prev_node[i] = -1;
			expanded[i] = false;
			best_root[i] = -1;
		}

		min_cost[start_node] = 0;
		do{
			// ̤Ÿ³«¤Î¥Î¡¼¥É¤Ç¡¢¥³¥¹¥È¤¬ºÇ¤âÄ㤤¥Î¡¼¥É¤òŸ³«
			int best_node = -1;
			float min = FLOAT_MAX;
			for(int i=0; i<MAX_NODE_COUNT; ++i){
				if(!expanded[i] && min > min_cost[i]){
					min = min_cost[i];
					best_node = i;
				}
			}
			if(best_node == -1){
				break;
			}
			for(int i=0; i<5; ++i){
				if(best_node == end_node[i]){
					break;
				}
			}

			expanded[best_node] = true;
			Vector2 v1, v2;
			for(int i=0; i<MAX_NODE_COUNT; ++i){
				// ¥Î¡¼¥Éi¤Ø¤Î¥ê¥ó¥¯¤¬Â¸ºß¤¹¤ë¤«¥Á¥§¥Ã¥¯
				if(link_[best_node][i] >= 0){
					float cost = min_cost[best_node] + link_[best_node][i];
					// Ä̾ï¤Î¥³¥¹¥È¤Ë¶Ê¤¬¤ë³ÑÅÙ¤ò¹Íθ¤·¤¿¥³¥¹¥È¤ò²Ã»»
					if(best_node != start_node){
						v1 = pos_list_[best_node].pos - pos_list_[prev_node[best_node]].pos;
						v2 = pos_list_[i].pos - pos_list_[best_node].pos;
						if(v1.getLength() * v2.getLength() > 0){
							float cos = (0.001f + (-(Cos(v1, v2) - 1.0f)/2.0f)) * 0.999f;	// ¡Ú·×»»¸íº¹Âкö¤Ë¤È¤ê¤¢¤¨¤º0.001f¤ò­¤·¤Æ0.999f¤ò¤«¤±¤Æ¤ª¤¯¡Û
							cost += corner_rate_ * MAX_VEL * cos;
						}
					}
					// ¥³¥¹¥È¤¬Á°¤è¤ê¤âÄ㤱¤ì¤Ð¹¹¿·
					if(min_cost[i] > cost){
						min_cost[i] = cost;
						prev_node[i] = best_node;
					}
				}
			}
		}while(1);

		// ¥Ù¥¹¥È¤Ê½ªÎ»¥Î¡¼¥É¤ò¼èÆÀ
		float min = FLOAT_MAX, cost;
		int best_end_node = -1;
		for(int i=0; i<5; ++i){
			cost = min_cost[end_node[i]];
			if(min > cost){
				min = cost;
				best_end_node = end_node[i];
			}
		}

		// ¥Ù¥¹¥È¤Ê¥ë¡¼¥È¤ò¼èÆÀ
		int c = 0;
		for(int n=best_end_node; prev_node[n]!=-1; n=prev_node[n], ++c){}	// ¥ë¡¼¥È¤ÎŤµ¼èÆÀ
		for(int n=best_end_node, j=0; prev_node[n]!=-1; n=prev_node[n], ++j){
			best_root[c-j] = n;
		}
		best_root[0] = start_node;

		return min_cost[best_end_node];
	}
};

//=============================================================================================//
//     ¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤ÎºîÀ®
//=============================================================================================//
float MakeCheckPoints(const Field& aField, Vector2 check_points[MAX_NODE_COUNT], int *check_point_count, bool jump, float corner_rate){
	// ĺÅÀ¥ê¥¹¥È¤ÎºîÀ®
	Node pos_list[MAX_NODE_COUNT];
	int pos_list_count = 0;
	Vector2 pos;
	Vector2 deltas[] = {
		Vector2(-DELTA, -DELTA),	// Rect::CornerKind_LeftUp
		Vector2(-DELTA,  DELTA),	// Rect::CornerKind_LeftDown
		Vector2( DELTA, -DELTA),	// Rect::CornerKind_RightUp
		Vector2( DELTA,  DELTA)		// Rect::CornerKind_RightDown
	};
	const int deltas_count = sizeof(deltas)/sizeof(Vector2);
	// ¤½¤ì¤¾¤ì¤Î·ê¤Î³ÑÉÕ¶á¤ËĺÅÀ¤ò¼è¤ë
	const int corner_type_count = sizeof(CORNER_KINDS)/sizeof(Rect::CornerKind);
	for(int i=0; i<aField.getHoleCount(); ++i){
		bool flag[corner_type_count] = {};
		for(int j=0; j<deltas_count; ++j){
			for(int k=0; k<corner_type_count; ++k){
				// ¤½¤Î¤Þ¤Þ»Í¶ù¤ÎºÂɸ¤ò»È¤¦¤È·ê¤ËÍî¤Á¤ë¤Î¤Ç¤Á¤ç¤Ã¤È¤º¤é¤¹(¤º¤é¤·¤¿À褬Ê̤ηê¤È¤¤¤¦²ÄǽÀ­¤â¤¢¤ë¤Î¤Ç4Êý¸þ¤Ë¤º¤é¤¹¤Î¤ò»î¤¹)
				pos = aField.getHole(i).getCornerPos(CORNER_KINDS[k])   +deltas[(j+k)%deltas_count];
				// pos¤Ç·ê¤ËÍî¤Á¤Ê¤±¤ì¤Ð¥ê¥¹¥È¤ËÄɲÃ
				if(!flag[k] && !aField.isInHole(pos)){
					flag[k] = true;
					pos_list[pos_list_count++] = Node(pos, i, CORNER_KINDS[k]);
				}
			}
		}
	}
	// ·ê¤È·ê¤Î¸òÅÀÉÕ¶á¤ËĺÅÀ¤ò¼è¤ë
	Vector2 point_list[4];
	int point_count;
	for(int i=0; i<aField.getHoleCount(); ++i){
		for(int j=i+1; j<aField.getHoleCount(); ++j){
			if(CrossPoint(aField.getHole(i), aField.getHole(j), point_list, &point_count)){
				bool flag[4] = {};
				for(int k=0; k<point_count; ++k){
					for(int l=0; l<deltas_count; ++l){
						pos = point_list[k] + deltas[l];
						if(!flag[k] && !aField.isInHole(pos)){
							flag[k] = true;
							pos_list[pos_list_count++] = Node(pos, Node::Type_Else);
						}
					}
				}
			}
		}
	}
	// ¥¹¥¿¡¼¥È¤È¥´¡¼¥ë(»Í¶ù¡ÜÃæ¿´)¤òĺÅÀ¤È¤¹¤ë
	int start_id = pos_list_count;
	pos_list[pos_list_count++] = Node(aField.getStartPos(), Node::Type_Start);
	int goal_id_list[5] = {pos_list_count};
	pos_list[pos_list_count++] = Node(aField.getGoalRect().getCenterPos(), Node::Type_Goal);
	{
		bool flag[corner_type_count] = {};
		for(int k=0; k<corner_type_count; ++k){
			pos = aField.getGoalRect().getCornerPos(CORNER_KINDS[k]) - deltas[k];
			if(!aField.isInHole(pos)){
				goal_id_list[pos_list_count-goal_id_list[0]] = pos_list_count;
				pos_list[pos_list_count++] = Node(pos, Node::Type_Goal);
			}
		}
	}

	// ¥³¥¹¥ÈÉÕ¤­Ìµ¸þ¥°¥é¥Õ¤ÎºîÀ®
	DijkstraAlgorithm dijkstra(pos_list, corner_rate);
	float cost;
	for(int i=0; i<pos_list_count; ++i){
		for(int j=i+1; j<pos_list_count; ++j){
			// ¥Î¡¼¥É¤ò·ë¤Ö¥¨¥Ã¥¸¤¬·ê¤È¸òº¹¤·¤Æ¤¤¤Ê¤±¤ì¤Ð¥¨¥Ã¥¸¤òÄɲÃ
			if(!isCrossHole(aField, pos_list[i].pos, pos_list[j].pos, jump)){
				// ¥³¥¹¥È¤ò·×»»¤·¥¨¥Ã¥¸¤òÄɲÃ
				cost = (pos_list[i].pos - pos_list[j].pos).getLength();
				if(!Equal(cost, 0.0f)){
					dijkstra.SetLink(i, j, cost);
				}
			}
		}
	}
	
	// ¥À¥¤¥¯¥¹¥È¥é¤Ç²ò¤¯
	int check_point_id_list[MAX_NODE_COUNT];
	float length = dijkstra.Solve(start_id, goal_id_list, check_point_id_list);

	// ¡Ú¥Ç¥Ð¥Ã¥°ÍѽÐÎÏ¡Û
	HAL_PRINT("best root %s[", ((jump)? "(jump)": ""));
	char direction[4][5] = {
		"º¸¾å",
		"±¦¾å",
		"±¦²¼",
		"º¸²¼"
	};
	Vector2 prev;
	for(unsigned int i=0; check_point_id_list[i]!=-1; ++i){
		switch(pos_list[check_point_id_list[i]].type){
			case Node::Type_Corner:
				HAL_PRINT("%d%s(%.2f, %.2f) ",
					pos_list[check_point_id_list[i]].hole_id, direction[pos_list[check_point_id_list[i]].corner],
					pos_list[check_point_id_list[i]].pos.x,
					pos_list[check_point_id_list[i]].pos.y
				);
				break;
			case Node::Type_Start:
				HAL_PRINT("start(%.2f, %.2f) ", pos_list[check_point_id_list[i]].pos.x, pos_list[check_point_id_list[i]].pos.y);
				break;
			case Node::Type_Goal:
				HAL_PRINT("end(%.2f, %.2f)", pos_list[check_point_id_list[i]].pos.x, pos_list[check_point_id_list[i]].pos.y);
				break;
			default:
				HAL_PRINT(" (%.2f, %.2f)", pos_list[check_point_id_list[i]].pos.x, pos_list[check_point_id_list[i]].pos.y);
				break;

		}
		if(i != 0){
			IMG_DATA_PRINT("%f %f %f %f %s\n", prev.x, prev.y, pos_list[check_point_id_list[i]].pos.x, pos_list[check_point_id_list[i]].pos.y, DEBUG_LINE_COLOR1);
		}
		prev = pos_list[check_point_id_list[i]].pos;
	}
	HAL_PRINT("]\n\n");

	// ¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¥ê¥¹¥È¤ÎºîÀ®
	*check_point_count = 0;
	for(int i=0; check_point_id_list[i]!=-1; ++i){
		check_points[(*check_point_count)++] = pos_list[check_point_id_list[i]].pos;
	}

	return length;
}

//=============================================================================================//
//     ¸½ºß¤Î®ÅÙ¤«¤é»ß¤Þ¤ë¤Î¤ËºÇÄã¸ÂɬÍפʵ÷Î¥¤Î¼èÆÀ
//=============================================================================================//
float StopDistance(const float vel){
	unsigned int n = (unsigned int)(vel / MAX_ACCEL);	// ¾¦
	float a = vel - n * MAX_ACCEL;	// ¾ê;

	return (MAX_ACCEL * (n * (n-1))/2) + a * n;
}

//=============================================================================================//
//     ¥Ç¥Õ¥©¥ë¥È¤Î¥¢¥¯¥·¥ç¥ó¤ÎºîÀ®
//=============================================================================================//
void MakeDefaultActions(
	const Field& aField,
	const Vector2 check_points[MAX_NODE_COUNT],
	const int check_point_count,
	Action actions[MAX_TURN_COUNT],	// ºîÀ®¤µ¤ì¤¿¥¢¥¯¥·¥ç¥ó
	int turns[MAX_NODE_COUNT]	// ³Æ¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤òÄ̲᤹¤ë¤Î¤Ë¤«¤«¤Ã¤¿¥¿¡¼¥ó¿ô
){
	Status status(aField.getStartPos(), Vector2());
	int current_point_id = 0;
	Vector2 last_ball_pos;

	// ¡Ú¼ÂºÝ¤Ëư¤«¤µ¤Ê¤¯¤Æ¤â¥¢¥¯¥·¥ç¥ó¤È¥¿¡¼¥ó¿ô¤È¤«·×»»¤Ç¤­¤½¤¦¤À¤±¤É¡¢¤È¤ê¤¢¤¨¤º¤³¤ì¤Ç±þµÞ½èÃÖ¡Û

	int action_count = 0;
	int turns_count = 0;
	int turn = 0;
	turns[current_point_id++] = turn;
	do{
		++turn;

		Vector2 start = status.getBallPos(),
			end = check_points[current_point_id];
	    Vector2 accel = end - start;

		// ²Ã®Å٤ηèÄê
		float distance = accel.getLength();
		if(current_point_id == check_point_count-1){
			// ¼¡¤¬¥´¡¼¥ë¤Ê¤é¾ï¤Ë²Ã®
			accel.changeLength(MAX_ACCEL);
		}
		else if(Equal(distance, 0.0f)){
			// ®ÅÙ¤¬0¤Ë¤Ê¤ë¤è¤¦¤Ë¸ºÂ®
			accel = status.getBallVel();
			accel = Vector2(-accel.x, -accel.y);
			turns[current_point_id++] = turn;
		}
		else if(distance <= MAX_ACCEL && distance <= status.getBallVel().getLength()){
			// ÌÜɸ¤Î°ÌÃ֤˻ߤޤë¤è¤¦¤Ë¸ºÂ®
			accel.changeLength(MAX(status.getBallVel().getLength() - distance, 0));
			accel = Vector2(-accel.x, -accel.y);
		}
		else{
			float v = MIN(status.getBallVel().getLength() + MAX_ACCEL, MAX_VEL);
			if(status.getBallVel().getLength() < MAX_VEL && distance - v >= StopDistance(v)){
				// ²Ã®
				accel.changeLength(MAX_ACCEL);
			}
			else if(distance - status.getBallVel().getLength() >= StopDistance(status.getBallVel().getLength())){
				// ²Ã®¤â¸ºÂ®¤â¤·¤Ê¤¤
				accel = Vector2(0, 0);
			}
			else{
				// ¸ºÂ®
				accel.changeLength(MAX_ACCEL);
				accel = Vector2(-accel.x, -accel.y);
			}
		}

		// ¾õÂ֤ι¹¿·¤È¥¢¥¯¥·¥ç¥ó¤ÎÊݸ
		Action action(accel);
		last_ball_pos = status.getBallPos();
		status.update(action);
		actions[action_count++] = action;
	}while(!aField.isInGoal(last_ball_pos, status.getBallPos()));
	turns[current_point_id] = turn;
}

//**********************************************************************************************//
//*     ¥¤¥Ù¥ó¥È½èÍý
//**********************************************************************************************//

//=============================================================================================//
//     ¥×¥í¥°¥é¥à¤Î½é´ü²½
//=============================================================================================//
void onStartEvaluation() {
	for(int i=0; i<ACCEL_DIRECTION_MAX-1; ++i){
		ACCEL_VECTOR[i].normalize();
	}
}

//=============================================================================================//
//     ¥×¥í¥°¥é¥à¤Î½ªÎ»½èÍý
//=============================================================================================//
void onEndEvaluation() {
}

//=============================================================================================//
//     ¥²¡¼¥à¤Î½é´ü²½(¤³¤³¤Ç¥¢¥¯¥·¥ç¥ó¤òºÇ¸å¤Þ¤Ç·è¤á¤Æ¤·¤Þ¤¤¡¢¤¢¤È¤Ï½çÈ֤˥¢¥¯¥·¥ç¥ó¤ò¼Â¹Ô¤¹¤ë¤À¤±)
//=============================================================================================//
Action actions_[MAX_TURN_COUNT];

void onStartOneGame(const Field& aField) {
	++gameIndex_;
	turnIndex_ = 0;

	// Âç¤Þ¤«¤Ê¥ë¡¼¥È¤ò·è¤á¤ë¤¿¤á¡¢¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤òºîÀ®(¥¸¥ã¥ó¥×¤¢¤ê¤È¥¸¥ã¥ó¥×¤Ê¤·¤Ç2¥Ñ¥¿¡¼¥ó)
	Vector2 non_jump_check_points[MAX_NODE_COUNT], jump_check_points[MAX_NODE_COUNT];
	int non_jump_check_point_count, jump_check_point_count;
	float length1 = MakeCheckPoints(aField, non_jump_check_points, &non_jump_check_point_count, false, 6.5f);
	float length2 = MakeCheckPoints(aField, jump_check_points, &jump_check_point_count, true, 6.5f);
	// ¤È¤ê¤¢¤¨¤º¡¢Ã±½ã¤Ê¥¢¥ë¥´¥ê¥º¥à¤Ç¥Ç¥Õ¥©¥ë¥È¤Î¥¢¥¯¥·¥ç¥ó¤òºîÀ®
	//  ¡Ü¤½¤Î¾ì¹ç¤Î¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¤´¤È¤Ë¤«¤«¤Ã¤¿¥¿¡¼¥ó¿ô¤ò¼èÆÀ
	int turns[MAX_NODE_COUNT];
	MakeDefaultActions(aField, non_jump_check_points, non_jump_check_point_count, actions_, turns);

	// ¡Ú¥Ç¥Ð¥Ã¥°ÍѽÐÎÏ¡Û
	HAL_PRINT("turns: [ ");
	for(int i=0; i<non_jump_check_point_count; ++i){
		HAL_PRINT("%d ", turns[i]);
	}
	HAL_PRINT("]\n\n");

	// ¥Ç¥Õ¥©¥ë¥È¤Î¥¢¥¯¥·¥ç¥ó¤è¤ê¤âÎɤ¤¥¢¥¯¥·¥ç¥ó¤òõº÷
	if(non_jump_check_point_count > 2){
		int limit = turns[non_jump_check_point_count-1];
		int result = MakeActions(aField, jump_check_points, jump_check_point_count, true, limit, actions_);

		// non_jump_check_points¤Èjump_check_points¤¬°ã¤¦¥Á¥§¥Ã¥¯¥Ý¥¤¥ó¥È¥ê¥¹¥È¤Ê¤énon_jump_check_point_count¤Ç¤âõº÷
		if(!Equal(length1, length2)){
			limit = (result == 0)? limit: result;
			result = MakeActions(aField, non_jump_check_points, non_jump_check_point_count, false, limit, actions_);
		}
	}

	IMG_DATA_PRINT("\n");
}

//=============================================================================================//
//     ¥²¡¼¥à¤Î½ªÎ»½èÍý
//=============================================================================================//
void onEndOneGame() {
	HAL_PRINT("--------------------------------------------------------------------------\n");
}

//=============================================================================================//
//     ¥¢¥¯¥·¥ç¥ó¤Î¼Â¹Ô
//=============================================================================================//
Action decideAction(const Field& aField, const Status& aStatus) {
	++turnIndex_;
	// ¡Ú¥Ç¥Ð¥Ã¥°ÍѽÐÎÏ¡Û
	HAL_PRINT("-----[game %d: turn %d]---------------------------------------------------\n", gameIndex_, turnIndex_);
	HAL_PRINT("pos: (%.2f, %.2f)  vel: %.2f(%.2f, %.2f)  rest: %.2f\n",
		aStatus.getBallPos().x, aStatus.getBallPos().y,
		aStatus.getBallVel().getLength(), aStatus.getBallVel().x, aStatus.getBallVel().y,
		(aField.getGoalRect().getCenterPos() - aStatus.getBallPos()).getLength()
	);
	
	// ¥¢¥¯¥·¥ç¥ó¤Î¼èÆÀ
	Action action;
	action = actions_[turnIndex_-1];

	// ¡Ú¥Ç¥Ð¥Ã¥°ÍѽÐÎÏ¡Û
	HAL_PRINT("action: %.2f (%.2f, %.2f)\n", action.getAccel().getLength(), action.getAccel().x, action.getAccel().y);
	HAL_PRINT("\n");

	return action;
}