arg === null){ return true; } $destNationIDList = $this->arg['destNationIDList']??null; //null은 에러, []는 정상 if($destNationIDList === null || !is_array($destNationIDList)){ return true; } if($destNationIDList && Util::isDict($destNationIDList)){ return false; } foreach($destNationIDList as $nationID){ if(!is_int($nationID)){ return false; } if($nationID < 1){ return false; } } $this->arg = [ 'destNationIDList' => $destNationIDList ]; return true; } protected function init(){ $general = $this->generalObj; $env = $this->env; $this->setCity(); $this->setNation(); $relYear = $env['year'] - $env['startyear']; $this->runnableConstraints=[ ConstraintHelper::BeNeutral(), ConstraintHelper::AllowJoinAction(), ]; if($this->arg['destNationIDList']??false){ $this->runnableConstraints[] = ConstraintHelper::ExistsAllowJoinNation($relYear, $this->arg['destNationIDList']); } } public function getCost():array{ return [0, 0]; } public function getPreReqTurn():int{ return 0; } public function getPostReqTurn():int{ return 0; } public function run():bool{ if(!$this->isRunnable()){ throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도'); } $db = DB::db(); $env = $this->env; $general = $this->generalObj; $date = $general->getTurnTime($general::TURNTIME_HM); $generalName = $general->getName(); $josaYi = JosaUtil::pick($generalName, '이'); $relYear = $env['year'] - $env['startyear']; $notIn = array_merge($general->getAuxVar('joinedNations')??[], $this->arg['destNationIDList']); $destNation = null; if ($general->getVar('npc') >= 2 && !$env['fiction'] && 1000 <= $env['scenario'] && $env['scenario'] < 2000) { if($notIn){ $nations = $db->query( 'SELECT nation.`name` as `name`,nation.nation as nation,scout,gennum,`affinity` FROM nation join general on general.nation = nation.nation and general.level = 12 WHERE scout=0 and gennum<%i and nation.nation not in %li', $relYear<3?GameConst::$initialNationGenLimit:GameConst::$defaultMaxGeneral, $notIn ); } else{ $nations = $db->query( 'SELECT nation.`name` as `name`,nation.nation as nation,scout,gennum,`affinity` FROM nation join general on general.nation = nation.nation and general.level = 12 WHERE scout=0 and gennum<%i', $relYear<3?GameConst::$initialNationGenLimit:GameConst::$defaultMaxGeneral ); } shuffle($nations); $allGen = Util::arraySum($nations, 'gennum'); $maxScore = 1<<30; $affinity = $general->getVar('affinity'); foreach($nations as $testNation){ $affinity = abs($affinity - $testNation['affinity']); $affinity = min($affinity, abs($affinity - 150)); $score = log($affinity + 1, 2);//0~ //쉐킷쉐킷 $score += Util::randF(); $score += sqrt($testNation['gennum']/$allGen); if($score < $maxScore){ $maxScore = $score; $destNation = $testNation; } } } else{ $onlyRandom = $env['join_mode'] == 'onlyRandom'; $genLimit = GameConst::$defaultMaxGeneral; if($onlyRandom && TimeUtil::IsRangeMonth($env['init_year'], $env['init_month'], 1, $env['year'], $env['month'])){ $genLimit = GameConst::$initialNationGenLimitForRandInit; } else if($relYear < 3){ $genLimit = GameConst::$initialNationGenLimit; } $generalsCnt = []; if($notIn){ $rawGeneralsCnt = $db->query( 'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE npc < 5 AND nation.gennum < %i AND nation.nation NOT IN %li GROUP BY general.nation, general.npc', $genLimit, $notIn ); } else{ $rawGeneralsCnt = $db->query( 'SELECT general.nation as nation, nation.gennum, nation.name, npc, count(*) as cnt FROM general JOIN nation ON general.nation = nation.nation WHERE npc < 5 AND nation.gennum < %i GROUP BY general.nation, general.npc', $genLimit ); } foreach($rawGeneralsCnt as $nation){ $nationID = $nation['nation']; if(!\key_exists($nationID, $generalsCnt)){ $generalsCnt[$nationID] = [ 'nation'=>$nationID, 'gennum'=>$nation['gennum'], 'name'=>$nation['name'], 'cnt'=>0, ]; $generalsCnt[$nationID]['cnt'] = 0; } if($nation['npc'] <= 2){ $calcCnt = $nation['cnt']; } else{ $calcCnt = $nation['cnt'] / 2; } $generalsCnt[$nationID]['cnt'] += $calcCnt; } $randVals = []; foreach($generalsCnt as $testNation){ $randVals[] = [$testNation, 1/$testNation['cnt']]; } $destNation = Util::choiceRandomUsingWeightPair($randVals); } $logger = $general->getLogger(); if(!$destNation){ //임관 가능한 국가가 없다! $logger->pushGeneralActionLog("임관 가능한 국가가 없습니다. <1>$date"); $this->alternative = new che_요양($general, $this->env, null); return false; } $gennum = $destNation['gennum']; $destNationID = $destNation['nation']; $destNationName = $destNation['name']; $talkList = [ '어쩌다 보니', '인연이 닿아', '발길이 닿는 대로', '소문을 듣고', '점괘에 따라', ]; $randomTalk = Util::choiceRandom($talkList); $logger->pushGeneralActionLog("{$destNationName}에 랜덤 임관했습니다. <1>$date"); $logger->pushGeneralHistoryLog("{$destNationName}에 랜덤 임관"); $logger->pushGlobalActionLog("{$generalName}{$josaYi} {$randomTalk} {$destNationName}임관했습니다."); if($gennum < GameConst::$initialNationGenLimit) { $exp = 700; } else { $exp = 100; } $general->setVar('nation', $destNationID); $general->setVar('level', 1); $general->setVar('belong', 1); if($this->destGeneralObj !== null){ $general->setVar('city', $this->destGeneralObj->getCityID()); } else{ $targetCityID = $db->queryFirstField('SELECT city FROM general WHERE nation = %i AND level=12', $destNationID); $general->setVar('city', $targetCityID); } $db->update('nation', [ 'gennum'=>$db->sqleval('gennum + 1') ], 'nation=%i', $destNationID); $relYear = $env['year'] - $env['startyear']; if($general->getVar('npc') == 1 || $relYear >= 3){ $joinedNations = $general->getAuxVar('joinedNations')??[]; $joinedNations[] = $destNationID; $general->setAuxVar('joinedNations', $joinedNations); } $general->addExperience($exp); $general->setResultTurn(new LastTurn(static::getName(), $this->arg)); $general->checkStatChange(); tryUniqueItemLottery($general, '랜덤 임관'); $general->applyDB($db); return true; } }