/*
¥Ï¥ë¸¦µæ½ê¥×¥í¥°¥é¥ß¥ó¥°¥³¥ó¥Æ¥¹¥È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;
}