feat: NPC 거병, 이동 로직 대폭 개선

- 근처에 세울 도시를 보고 거병
- 원하는 도시를 정하고 그 도시를 향해 이동
This commit is contained in:
2021-11-14 05:06:39 +09:00
parent 3c28ceb701
commit a560ee6f0a
+93 -28
View File
@@ -116,8 +116,8 @@ class GeneralAI
$nationStor = KVStorage::getStorage($db, $this->nation['nation'], 'nation_env');
$nationStor->cacheValues(['npc_nation_policy', 'npc_general_policy', 'prev_income_gold', 'prev_income_rice']);
$this->nationPolicy = new AutorunNationPolicy($general, $this->env['autorun_user']['options'], $nationStor->getValue('npc_nation_policy'), $gameStor->getValue('npc_nation_policy'), $this->nation, $this->env);
$this->generalPolicy = new AutorunGeneralPolicy($general, $this->env['autorun_user']['options'], $nationStor->getValue('npc_general_policy'), $gameStor->getValue('npc_general_policy'), $this->nation, $this->env);
$this->nationPolicy = new AutorunNationPolicy($general, $this->env['autorun_user']['options']??null, $nationStor->getValue('npc_nation_policy'), $gameStor->getValue('npc_nation_policy'), $this->nation, $this->env);
$this->generalPolicy = new AutorunGeneralPolicy($general, $this->env['autorun_user']['options']??null, $nationStor->getValue('npc_general_policy'), $gameStor->getValue('npc_general_policy'), $this->nation, $this->env);
$prevIncomeGold = $nationStor->prev_income_gold ?? 1000;
$prevIncomeRice = $nationStor->prev_income_rice ?? 1000;
@@ -3082,7 +3082,7 @@ class GeneralAI
$general = $this->general;
$lordCities = $db->queryFirstColumn('SELECT city.city as city FROM general LEFT JOIN city ON general.city = city.city WHERE general.officer_level = 12 AND city.nation = 0');
$nationCities = $db->queryFirstColumn('SELECT city a FROM city WHERE nation != 0');
$nationCities = $db->queryFirstColumn('SELECT city FROM city WHERE nation != 0');
$occupiedCities = [];
foreach ($lordCities as $tCityId) {
@@ -3092,38 +3092,62 @@ class GeneralAI
$occupiedCities[$tCityId] = 1;
}
$movingTargetCityID = $general->getAuxVar('movingTargetCityID');
$currCityID = $general->getCityID();
$targetCity = [];
if($movingTargetCityID === $currCityID){
$movingTargetCityID = null;
}
else if(key_exists($movingTargetCityID, $occupiedCities)){
$movingTargetCityID = null;
}
//NOTE: 최단 거리가 현재 도시에서 '어떻게 가야' 가장 짧은지 알 수가 없으므로, 한칸 간 다음 계산하기로
//출발지가 정해져 있으므로, searchAllDistanceByCityList는 비효율적.
foreach (array_keys(CityConst::byID($currCityID)->path) as $nearCityID) {
if (CityConst::byID($nearCityID)->level < 4) {
$targetCity[$nearCityID] = 0.5;
} else if (!key_exists($nearCityID, $occupiedCities)) {
$targetCity[$nearCityID] = 2;
} else {
$targetCity[$nearCityID] = 0;
}
$distanceFrom = searchDistance($nearCityID, 4, true);
foreach ($distanceFrom as $distance => $distCities) {
foreach ($distCities as $distCity) {
if (key_exists($distCity, $occupiedCities)) {
continue;
}
if (CityConst::byID($distCity)->level < 4) {
continue;
}
$targetCity[$nearCityID] += 1 / (2 ** $distance);
if($movingTargetCityID === null){
//어느 도시로 갈 것인가?
$candidateCities = [];
foreach(searchDistance($currCityID, 4) as $testCityID => $dist){
if(key_exists($testCityID, $occupiedCities)){
continue;
}
$cityLevel = CityConst::byID($testCityID)->level;
if ($cityLevel < 5 || 6 < $cityLevel) {
continue;
}
$candidateCities[] = [$testCityID, 1 / pow(2, $dist)];
}
if(!$candidateCities){
return null;
}
$movingTargetCityID = Util::choiceRandomUsingWeightPair($candidateCities);
$general->setAuxVar('movingTargetCityID', $movingTargetCityID);
}
if($movingTargetCityID == $currCityID){
return buildGeneralCommandClass('che_인재탐색', $general, $this->env);
}
$distMap = searchDistance($movingTargetCityID, 99);
$targetDistance = $distMap[$currCityID];
$candidateCities = [];
foreach (array_keys(CityConst::byID($currCityID)->path) as $nearCityID) {
$cityLevel = CityConst::byID($nearCityID)->level;
if(5 <= $cityLevel && $cityLevel <= 6 && !key_exists($nearCityID, $occupiedCities)){
//바로 옆 도시로 이동하면 건국 가능하다면? 가보자
$candidateCities[] = [$nearCityID, 10];
}
if($distMap[$nearCityID] + 1 == $targetDistance){
$candidateCities[] = [$nearCityID, 1];
}
}
if(!$candidateCities){
return null;
}
$cmd = buildGeneralCommandClass('che_이동', $general, $this->env, [
'destCityID' => Util::choiceRandomUsingWeight($targetCity)
'destCityID' => Util::choiceRandomUsingWeightPair($candidateCities)
]);
if (!$cmd->hasFullConditionMet()) {
return null;
@@ -3146,6 +3170,43 @@ class GeneralAI
return null;
}
$currentCityLevel = CityConst::byID($general->getCityID())->level;
if (($currentCityLevel < 5 || 6 < $currentCityLevel) && Util::randBool(0.5)){
return null;
}
$db = DB::db();
$lordCities = $db->queryFirstColumn('SELECT city.city as city FROM general LEFT JOIN city ON general.city = city.city WHERE general.officer_level = 12 AND city.nation = 0');
$nationCities = $db->queryFirstColumn('SELECT city FROM city WHERE nation != 0');
$occupiedCities = [];
foreach ($lordCities as $tCityId) {
$occupiedCities[$tCityId] = 2;
}
foreach ($nationCities as $tCityId) {
$occupiedCities[$tCityId] = 1;
}
$availableNearCity = false;
foreach(searchDistance($general->getCityID(), 3) as $targetCityID => $dist){
if(key_exists($targetCityID, $occupiedCities)){
continue;
}
$cityLevel = CityConst::byID($targetCityID)->level;
if($cityLevel < 5 || 6 < $cityLevel){
continue;
}
if($dist == 3 && Util::randBool()){
continue;
}
$availableNearCity = true;
break;
}
if(!$availableNearCity){
return null;
}
$prop = Util::randF() * (GameConst::$defaultStatNPCMax + GameConst::$chiefStatMin) / 2;
$ratio = ($this->fullLeadership + $this->fullStrength + $this->fullIntel) / 3;
@@ -3156,7 +3217,7 @@ class GeneralAI
//XXX: 건국기한 2년
$more = Util::valueFit(3 - $this->env['year'] + $this->env['init_year'], 1, 3);
if (!Util::randBool(0.005 * $more)) {
if (!Util::randBool(0.0075 * $more)) {
return null;
}
@@ -3175,6 +3236,8 @@ class GeneralAI
return null;
}
$this->general->setAuxVar('movingTargetCityID', null);
return $cmd;
}
@@ -3191,6 +3254,8 @@ class GeneralAI
return null;
}
$this->general->setAuxVar('movingTargetCityID', null);
return $cmd;
}