diff --git a/hwe/b_myPage.php b/hwe/b_myPage.php
index 110bc8cb..923ba986 100644
--- a/hwe/b_myPage.php
+++ b/hwe/b_myPage.php
@@ -150,6 +150,11 @@ $use_auto_nation_turn = $me->getAuxVar('use_auto_nation_turn') ?? 1;
+
+ 거리 3칸 이내 아국 도시로 즉시 이동
+
+
+
npcmode == 2 && $me->getNPCType() == 0) : ?>
다른 장수 선택 (= substr($me->getAuxVar('next_change') ?? TimeUtil::now(), 0, 19) ?> 부터)
diff --git a/hwe/sammo/API/General/InstantRetreat.php b/hwe/sammo/API/General/InstantRetreat.php
new file mode 100644
index 00000000..5c8b4150
--- /dev/null
+++ b/hwe/sammo/API/General/InstantRetreat.php
@@ -0,0 +1,81 @@
+cacheAll();
+
+ $general = General::createObjFromDB($session->generalID);
+
+ if (!$general) {
+ return '장수가 없습니다';
+ }
+
+ increaseRefresh("접경귀환", 1);
+
+ $commandObj = buildGeneralCommandClass('che_접경귀환', $general, $gameStor->getAll(true));
+ $logger = $general->getLogger();
+
+ if (!$commandObj->hasFullConditionMet()) {
+ $logger->pushGeneralActionLog($commandObj->getFailString());
+ $reason = $commandObj->getFailString();
+ return $reason;
+ }
+
+ $result = $commandObj->run(new RandUtil(
+ new LiteHashDRBG(Util::simpleSerialize(
+ UniqueConst::$hiddenSeed,
+ 'InstantRetreat',
+ $general->getID(),
+ $gameStor->year,
+ $gameStor->month,
+ $general->getCityID(),
+ ))
+ ));
+
+ if (!$result) {
+ return '가까운 아국 도시가 없습니다.';
+ }
+
+ return null;
+ }
+}
diff --git a/hwe/sammo/Command/General/che_접경귀환.php b/hwe/sammo/Command/General/che_접경귀환.php
new file mode 100644
index 00000000..6c1df6b4
--- /dev/null
+++ b/hwe/sammo/Command/General/che_접경귀환.php
@@ -0,0 +1,107 @@
+arg = null;
+ return true;
+ }
+
+ protected function init()
+ {
+
+ $general = $this->generalObj;
+
+ $this->setCity();
+ $this->setNation();
+
+ [$reqGold, $reqRice] = $this->getCost();
+
+ $this->fullConditionConstraints=[
+ ConstraintHelper::NotBeNeutral(),
+ ConstraintHelper::NotWanderingNation(),
+ ConstraintHelper::NotOccupiedCity()
+ ];
+ }
+
+ public function getCost():array{
+ return [0, 0];
+ }
+
+ public function getPreReqTurn():int{
+ return 0;
+ }
+
+ public function getPostReqTurn():int{
+ return 0;
+ }
+
+ public function run(\Sammo\RandUtil $rng):bool{
+ if(!$this->hasFullConditionMet()){
+ throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
+ }
+
+ $db = DB::db();
+
+ $general = $this->generalObj;
+ $cityID = $general->getCityID();
+ $logger = $general->getLogger();
+
+ $distanceList = searchDistance($cityID, 3, true);
+
+ $occupiedCityList = new \Ds\Set($db->queryFirstColumn(
+ 'SELECT city FROM city WHERE nation = %i AND city IN %li AND supply = 1',
+ $general->getNationID(),
+ array_merge(...$distanceList)
+ ));
+
+ $nearestCityList = [];
+ foreach($distanceList as $cityList){
+ foreach($cityList as $cityID){
+ if($occupiedCityList->contains($cityID)){
+ $nearestCityList[] = $cityID;
+ }
+ }
+ if($nearestCityList){
+ break;
+ }
+ }
+
+ if(!$nearestCityList){
+ $logger->pushGeneralActionLog("3칸 이내에 아국 도시가 없습니다.");
+ return false;
+ }
+
+ $destCityID = $rng->choice($nearestCityList);
+ $destCityName = CityConst::byID($destCityID)->name;
+
+ $josaRo = JosaUtil::pick($destCityName, '로');
+ $logger->pushGeneralActionLog("{$destCityName}>{$josaRo} 접경귀환했습니다.");
+ $general->setVar('city', $destCityID);
+
+ //TODO: InstantAction일때에만 설정하지 않는게 나은데..
+ //$this->setResultTurn(new LastTurn(static::getName(), $this->arg));
+
+ $general->applyDB($db);
+
+ return true;
+ }
+
+
+}
\ No newline at end of file
diff --git a/hwe/ts/SammoAPI.ts b/hwe/ts/SammoAPI.ts
index 0db7d859..626f36d9 100644
--- a/hwe/ts/SammoAPI.ts
+++ b/hwe/ts/SammoAPI.ts
@@ -131,6 +131,7 @@ const apiRealPath = {
itemType: ItemTypeKey;
}>,
DieOnPrestart: POST as APICallT,
+ InstantRetreat: POST as APICallT,
BuildNationCandidate: POST as APICallT,
GetCommandTable: GET as APICallT,
GetFrontInfo: GET as APICallT<{
diff --git a/hwe/ts/myPage.ts b/hwe/ts/myPage.ts
index 354a8cd3..60bd69e0 100644
--- a/hwe/ts/myPage.ts
+++ b/hwe/ts/myPage.ts
@@ -170,6 +170,26 @@ $(function ($) {
location.reload();
});
+ $('#instantRetreat').on('click', async function (e) {
+ e.preventDefault();
+
+ if(!confirm('아군 접경으로 이동할까요?')){
+ return false;
+ }
+
+ try {
+ await SammoAPI.General.InstantRetreat();
+ }
+ catch (e) {
+ console.log(e);
+ alert(`실패했습니다: ${e}`);
+ location.reload();
+ return;
+ }
+
+ location.reload();
+ });
+
$('#vacation').on('click', async function (e) {
e.preventDefault();
if (!confirm('휴가 기능을 신청할까요?')) {