랜덤 임관 버그 수정

This commit is contained in:
2020-06-05 18:13:21 +09:00
parent 0f5ba4ef5b
commit 90b970115a
+299 -299
View File
@@ -1,300 +1,300 @@
<?php <?php
namespace sammo\Command\General; namespace sammo\Command\General;
use \sammo\{ use \sammo\{
DB, Util, JosaUtil, TimeUtil, Json, DB, Util, JosaUtil, TimeUtil, Json,
General, General,
ActionLogger, ActionLogger,
GameConst, GameUnitConst, GameConst, GameUnitConst,
LastTurn, LastTurn,
Command Command
}; };
use function \sammo\{ use function \sammo\{
tryUniqueItemLottery, tryUniqueItemLottery,
getInvitationList, getInvitationList,
getNationStaticInfo getNationStaticInfo
}; };
use \sammo\Constraint\Constraint; use \sammo\Constraint\Constraint;
use \sammo\Constraint\ConstraintHelper; use \sammo\Constraint\ConstraintHelper;
use sammo\CityConst; use sammo\CityConst;
use sammo\MustNotBeReachedException; use sammo\MustNotBeReachedException;
class che_랜덤임관 extends Command\GeneralCommand{ class che_랜덤임관 extends Command\GeneralCommand{
static protected $actionName = '랜덤임관'; static protected $actionName = '랜덤임관';
protected function argTest():bool{ protected function argTest():bool{
$this->arg = null; $this->arg = null;
return true; return true;
//TODO: 구현 //TODO: 구현
/*if($this->arg === null){ /*if($this->arg === null){
return true; return true;
} }
$destNationIDList = $this->arg['destNationIDList']??null; $destNationIDList = $this->arg['destNationIDList']??null;
//null은 에러, []는 정상 //null은 에러, []는 정상
if($destNationIDList === null || !is_array($destNationIDList)){ if($destNationIDList === null || !is_array($destNationIDList)){
return true; return true;
} }
if($destNationIDList && Util::isDict($destNationIDList)){ if($destNationIDList && Util::isDict($destNationIDList)){
return false; return false;
} }
foreach($destNationIDList as $nationID){ foreach($destNationIDList as $nationID){
if(!is_int($nationID)){ if(!is_int($nationID)){
return false; return false;
} }
if($nationID < 1){ if($nationID < 1){
return false; return false;
} }
} }
$this->arg = [ $this->arg = [
'destNationIDList' => $destNationIDList 'destNationIDList' => $destNationIDList
]; ];
return true;*/ return true;*/
} }
protected function init() protected function init()
{ {
$general = $this->generalObj; $general = $this->generalObj;
$env = $this->env; $env = $this->env;
$this->setCity(); $this->setCity();
$this->setNation(); $this->setNation();
$relYear = $env['year'] - $env['startyear']; $relYear = $env['year'] - $env['startyear'];
$this->fullConditionConstraints=[ $this->fullConditionConstraints=[
ConstraintHelper::BeNeutral(), ConstraintHelper::BeNeutral(),
ConstraintHelper::AllowJoinAction(), ConstraintHelper::AllowJoinAction(),
]; ];
/* /*
if($this->arg['destNationIDList']??false){ if($this->arg['destNationIDList']??false){
$this->fullConditionConstraints[] = ConstraintHelper::ExistsAllowJoinNation($relYear, $this->arg['destNationIDList']); $this->fullConditionConstraints[] = ConstraintHelper::ExistsAllowJoinNation($relYear, $this->arg['destNationIDList']);
} }
*/ */
} }
public function getCommandDetailTitle():string{ public function getCommandDetailTitle():string{
return '무작위 국가로 임관'; return '무작위 국가로 임관';
} }
public function getBrief():string{ public function getBrief():string{
return '무작위 국가로 임관'; return '무작위 국가로 임관';
} }
public function getCost():array{ public function getCost():array{
return [0, 0]; return [0, 0];
} }
public function getPreReqTurn():int{ public function getPreReqTurn():int{
return 0; return 0;
} }
public function getPostReqTurn():int{ public function getPostReqTurn():int{
return 0; return 0;
} }
public function run():bool{ public function run():bool{
if(!$this->hasFullConditionMet()){ if(!$this->hasFullConditionMet()){
throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도'); throw new \RuntimeException('불가능한 커맨드를 강제로 실행 시도');
} }
$db = DB::db(); $db = DB::db();
$env = $this->env; $env = $this->env;
$general = $this->generalObj; $general = $this->generalObj;
$date = $general->getTurnTime($general::TURNTIME_HM); $date = $general->getTurnTime($general::TURNTIME_HM);
$generalName = $general->getName(); $generalName = $general->getName();
$josaYi = JosaUtil::pick($generalName, '이'); $josaYi = JosaUtil::pick($generalName, '이');
$relYear = $env['year'] - $env['startyear']; $relYear = $env['year'] - $env['startyear'];
/* /*
$notIn = array_merge($general->getAuxVar('joinedNations')??[], $this->arg['destNationIDList']); $notIn = array_merge($general->getAuxVar('joinedNations')??[], $this->arg['destNationIDList']);
*/ */
$notIn = null; $notIn = null;
$destNation = null; $destNation = null;
if ($general->getNPCType() >= 2 && !$env['fiction'] && 1000 <= $env['scenario'] && $env['scenario'] < 2000) { if ($general->getNPCType() >= 2 && !$env['fiction'] && 1000 <= $env['scenario'] && $env['scenario'] < 2000) {
if($notIn){ if($notIn){
$nations = $db->query( $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.officer_level = 12 WHERE scout=0 and gennum<%i and nation.nation not in %li', 'SELECT nation.`name` as `name`,nation.nation as nation,scout,gennum,`affinity` FROM nation join general on general.nation = nation.nation and general.officer_level = 12 WHERE scout=0 and gennum<%i and nation.nation not in %li',
$relYear<3?GameConst::$initialNationGenLimit:GameConst::$defaultMaxGeneral, $relYear<3?GameConst::$initialNationGenLimit:GameConst::$defaultMaxGeneral,
$notIn $notIn
); );
} }
else{ else{
$nations = $db->query( $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.officer_level = 12 WHERE scout=0 and gennum<%i', 'SELECT nation.`name` as `name`,nation.nation as nation,scout,gennum,`affinity` FROM nation join general on general.nation = nation.nation and general.officer_level = 12 WHERE scout=0 and gennum<%i',
$relYear<3?GameConst::$initialNationGenLimit:GameConst::$defaultMaxGeneral $relYear<3?GameConst::$initialNationGenLimit:GameConst::$defaultMaxGeneral
); );
} }
shuffle($nations); shuffle($nations);
$allGen = Util::arraySum($nations, 'gennum'); $allGen = Util::arraySum($nations, 'gennum');
$maxScore = 1<<30; $maxScore = 1<<30;
$affinity = $general->getVar('affinity'); $affinity = $general->getVar('affinity');
foreach($nations as $testNation){ foreach($nations as $testNation){
$affinity = abs($affinity - $testNation['affinity']); $affinity = abs($affinity - $testNation['affinity']);
$affinity = min($affinity, abs($affinity - 150)); $affinity = min($affinity, abs($affinity - 150));
$score = log($affinity + 1, 2);//0~ $score = log($affinity + 1, 2);//0~
//쉐킷쉐킷 //쉐킷쉐킷
$score += Util::randF(); $score += Util::randF();
$score += sqrt($testNation['gennum']/$allGen); $score += sqrt($testNation['gennum']/$allGen);
if($score < $maxScore){ if($score < $maxScore){
$maxScore = $score; $maxScore = $score;
$destNation = $testNation; $destNation = $testNation;
} }
} }
} }
else{ else{
$onlyRandom = $env['join_mode'] == 'onlyRandom'; $onlyRandom = $env['join_mode'] == 'onlyRandom';
$genLimit = GameConst::$defaultMaxGeneral; $genLimit = GameConst::$defaultMaxGeneral;
if($onlyRandom && TimeUtil::IsRangeMonth($env['init_year'], $env['init_month'], 1, $env['year'], $env['month'])){ if($onlyRandom && TimeUtil::IsRangeMonth($env['init_year'], $env['init_month'], 1, $env['year'], $env['month'])){
$genLimit = GameConst::$initialNationGenLimitForRandInit; $genLimit = GameConst::$initialNationGenLimitForRandInit;
} }
else if($relYear < 3){ else if($relYear < 3){
$genLimit = GameConst::$initialNationGenLimit; $genLimit = GameConst::$initialNationGenLimit;
} }
$generalsCnt = []; $generalsCnt = [];
if($notIn){ if($notIn){
$rawGeneralsCnt = $db->query( $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', '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.scout=0 AND nation.nation NOT IN %li GROUP BY general.nation, general.npc',
$genLimit, $genLimit,
$notIn $notIn
); );
} }
else{ else{
$rawGeneralsCnt = $db->query( $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', '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.scout=0 GROUP BY general.nation, general.npc',
$genLimit $genLimit
); );
} }
foreach($rawGeneralsCnt as $nation){ foreach($rawGeneralsCnt as $nation){
$nationID = $nation['nation']; $nationID = $nation['nation'];
if(!\key_exists($nationID, $generalsCnt)){ if(!\key_exists($nationID, $generalsCnt)){
$generalsCnt[$nationID] = [ $generalsCnt[$nationID] = [
'nation'=>$nationID, 'nation'=>$nationID,
'gennum'=>$nation['gennum'], 'gennum'=>$nation['gennum'],
'name'=>$nation['name'], 'name'=>$nation['name'],
'cnt'=>0, 'cnt'=>0,
]; ];
$generalsCnt[$nationID]['cnt'] = 0; $generalsCnt[$nationID]['cnt'] = 0;
} }
if($nation['npc'] <= 2){ if($nation['npc'] <= 2){
$calcCnt = $nation['cnt']; $calcCnt = $nation['cnt'];
} }
else{ else{
$calcCnt = $nation['cnt'] / 2; $calcCnt = $nation['cnt'] / 2;
} }
$generalsCnt[$nationID]['cnt'] += $calcCnt; $generalsCnt[$nationID]['cnt'] += $calcCnt;
} }
$randVals = []; $randVals = [];
foreach($generalsCnt as $testNation){ foreach($generalsCnt as $testNation){
$randVals[] = [$testNation, 1/$testNation['cnt']]; $randVals[] = [$testNation, 1/$testNation['cnt']];
} }
if($randVals){ if($randVals){
$destNation = Util::choiceRandomUsingWeightPair($randVals); $destNation = Util::choiceRandomUsingWeightPair($randVals);
} }
} }
$logger = $general->getLogger(); $logger = $general->getLogger();
if(!$destNation){ if(!$destNation){
//임관 가능한 국가가 없다! //임관 가능한 국가가 없다!
$logger->pushGeneralActionLog("임관 가능한 국가가 없습니다. <1>$date</>"); $logger->pushGeneralActionLog("임관 가능한 국가가 없습니다. <1>$date</>");
$this->alternative = new che_요양($general, $this->env, null); $this->alternative = new che_요양($general, $this->env, null);
return false; return false;
} }
$gennum = $destNation['gennum']; $gennum = $destNation['gennum'];
$destNationID = $destNation['nation']; $destNationID = $destNation['nation'];
$destNationName = $destNation['name']; $destNationName = $destNation['name'];
$talkList = [ $talkList = [
'어쩌다 보니', '어쩌다 보니',
'인연이 닿아', '인연이 닿아',
'발길이 닿는 대로', '발길이 닿는 대로',
'소문을 듣고', '소문을 듣고',
'점괘에 따라', '점괘에 따라',
'천거를 받아', '천거를 받아',
'유명한', '유명한',
'뜻을 펼칠 곳을 찾아', '뜻을 펼칠 곳을 찾아',
'고향에 가까운', '고향에 가까운',
'천하의 균형을 맞추기 위해', '천하의 균형을 맞추기 위해',
'오랜 은거를 마치고', '오랜 은거를 마치고',
]; ];
$randomTalk = Util::choiceRandom($talkList); $randomTalk = Util::choiceRandom($talkList);
$logger->pushGeneralActionLog("<D>{$destNationName}</>에 랜덤 임관했습니다. <1>$date</>"); $logger->pushGeneralActionLog("<D>{$destNationName}</>에 랜덤 임관했습니다. <1>$date</>");
$logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>에 랜덤 임관"); $logger->pushGeneralHistoryLog("<D><b>{$destNationName}</b></>에 랜덤 임관");
$logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} {$randomTalk} <D><b>{$destNationName}</b></>에 <S>임관</>했습니다."); $logger->pushGlobalActionLog("<Y>{$generalName}</>{$josaYi} {$randomTalk} <D><b>{$destNationName}</b></>에 <S>임관</>했습니다.");
if($gennum < GameConst::$initialNationGenLimit) { if($gennum < GameConst::$initialNationGenLimit) {
$exp = 700; $exp = 700;
} }
else { else {
$exp = 100; $exp = 100;
} }
$general->setVar('nation', $destNationID); $general->setVar('nation', $destNationID);
$general->setVar('officer_level', 1); $general->setVar('officer_level', 1);
$general->setVar('officer_city', 0); $general->setVar('officer_city', 0);
$general->setVar('belong', 1); $general->setVar('belong', 1);
if($this->destGeneralObj !== null){ if($this->destGeneralObj !== null){
$general->setVar('city', $this->destGeneralObj->getCityID()); $general->setVar('city', $this->destGeneralObj->getCityID());
} }
else{ else{
$targetCityID = $db->queryFirstField('SELECT city FROM general WHERE nation = %i AND officer_level=12', $destNationID); $targetCityID = $db->queryFirstField('SELECT city FROM general WHERE nation = %i AND officer_level=12', $destNationID);
$general->setVar('city', $targetCityID); $general->setVar('city', $targetCityID);
} }
$db->update('nation', [ $db->update('nation', [
'gennum'=>$db->sqleval('gennum + 1') 'gennum'=>$db->sqleval('gennum + 1')
], 'nation=%i', $destNationID); ], 'nation=%i', $destNationID);
$relYear = $env['year'] - $env['startyear']; $relYear = $env['year'] - $env['startyear'];
if($general->getNPCType() == 1 || $relYear >= 3){ if($general->getNPCType() == 1 || $relYear >= 3){
$joinedNations = $general->getAuxVar('joinedNations')??[]; $joinedNations = $general->getAuxVar('joinedNations')??[];
$joinedNations[] = $destNationID; $joinedNations[] = $destNationID;
$general->setAuxVar('joinedNations', $joinedNations); $general->setAuxVar('joinedNations', $joinedNations);
} }
$general->addExperience($exp); $general->addExperience($exp);
$this->setResultTurn(new LastTurn(static::getName(), $this->arg)); $this->setResultTurn(new LastTurn(static::getName(), $this->arg));
$general->checkStatChange(); $general->checkStatChange();
tryUniqueItemLottery($general, '랜덤 임관'); tryUniqueItemLottery($general, '랜덤 임관');
$general->applyDB($db); $general->applyDB($db);
return true; return true;
} }
} }