From 1ab45af036e3e21d1d77388ba5dd0a0d7728d8d6 Mon Sep 17 00:00:00 2001 From: hide_d Date: Sat, 4 Jan 2020 01:23:07 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B6=9C=EB=B3=91=EC=9D=84=20'=EC=96=B4?= =?UTF-8?q?=ED=83=9D=EB=95=85'=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENSE | 2 +- hwe/func.php | 65 ++++++++++++++++ hwe/func_process.php | 175 +++++++++++++++++++++++++++++-------------- hwe/processing.php | 3 +- index.php | 2 +- 5 files changed, 187 insertions(+), 60 deletions(-) diff --git a/LICENSE b/LICENSE index a5be8898..f44828e6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2019 Hide_D, 62che +Copyright (c) 2020 Hide_D, 62che Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/hwe/func.php b/hwe/func.php index 55c9ef55..bb2781b8 100644 --- a/hwe/func.php +++ b/hwe/func.php @@ -2786,6 +2786,71 @@ function searchDistance(int $from, int $maxDist=99, bool $distForm = false) { } } +/** + * $from 으로 지정한 도시의 인접 도시와 $to 도시의 최단 거리를 계산해 줌 + * @param $from 기준 도시 코드 + * @param $to 대상 도시 코드 + * @param $linkNationList 경로에 해당하는 국가 리스트 + * @return array $dist=>[cityID, $nation] 배열 가장 앞이 가장 가까움 + */ +function searchDistanceListToDest(int $from, int $to, array $linkNationList) { + $queue = new \SplQueue(); + + $cities = []; + + $db = DB::db(); + + //TODO: 도시-국가 캐싱이 있으면 쓸모 있지 않을까 + $allowedCityList = []; + foreach($db->queryAllLists( + 'SELECT city, nation FROM city WHERE nation IN %li', + $linkNationList + ) as [$cityID, $nationID]){ + $allowedCityList[$cityID] = $nationID; + } + + $remainFromCities = []; + foreach(array_keys(CityConst::byID($from)->path) as $fromCityID){ + if(key_exists($fromCityID, $allowedCityList)){ + $remainFromCities[$fromCityID] = true; + } + } + + if(!key_exists($to, $allowedCityList)){ + return []; + } + + $result = []; + $queue->enqueue([$to, 0]); + + while(!empty($remainFromCities) && !$queue->isEmpty()){ + list($cityID, $dist) = $queue->dequeue(); + if(key_exists($cityID, $cities)){ + continue; + } + + $cities[$cityID] = $dist; + + if(key_exists($cityID, $remainFromCities)){ + unset($remainFromCities[$cityID]); + $result[$dist][] = [$cityID, $allowedCityList[$cityID]]; + } + + foreach(array_keys(CityConst::byID($cityID)->path) as $connCityID){ + if($allowedCityList !== null && !key_exists($connCityID, $allowedCityList)){ + continue; + } + if(key_exists($connCityID, $cities)){ + continue; + } + $queue->enqueue([$connCityID, $dist+1]); + + } + } + + return $result; +} + function isNeighbor(int $nation1, int $nation2, bool $includeNoSupply=true) { if($nation1 === $nation2){ return false; diff --git a/hwe/func_process.php b/hwe/func_process.php index 9d384eb4..cc34f62c 100644 --- a/hwe/func_process.php +++ b/hwe/func_process.php @@ -1273,7 +1273,6 @@ function process_15(&$general) { function process_16(&$general) { $db = DB::db(); $gameStor = KVStorage::getStorage($db, 'game_env'); - $connect=$db->get(); $log = []; $alllog = []; @@ -1282,71 +1281,133 @@ function process_16(&$general) { $admin = $gameStor->getValues(['startyear', 'year', 'month']); - $query = "select nation,war,sabotagelimit,tech from nation where nation='{$general['nation']}'"; - $result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); - $nation = MYDB_fetch_array($result); - - $query = "select nation,supply from city where city='{$general['city']}'"; - $result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); - $city = MYDB_fetch_array($result); + $nation = $db->queryFirstRow('SELECT nation,war,sabotagelimit,tech from nation where nation=%i', $general['nation']); + $city = $db->queryFirstRow('SELECT nation,supply from city where city=%i', $general['city']); $command = DecodeCommand($general['turn0']); - $destination = $command[1]; + $finalTarget = $command[1]; + $finalDestCityName = CityConst::byID($finalTarget)->name; - $query = "select * from city where city='$destination'"; - $result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); - $destcity = MYDB_fetch_array($result); - - $query = "select nation,sabotagelimit,tech from nation where nation='{$destcity['nation']}'"; - $result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); - $dnation = MYDB_fetch_array($result); - - $query = "select state from diplomacy where me='{$general['nation']}' and you='{$destcity['nation']}'"; - $result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); - $dip = MYDB_fetch_array($result); - - if(key_exists($destination, CityConst::byID($general['city'])->path)){ - $nearCity = true; - } - else{ - $nearCity = false; - } - - $josaRo = JosaUtil::pick($destcity['name'], '로'); if($admin['year'] < $admin['startyear']+3) { - $log[] = "●{$admin['month']}월:현재 초반 제한중입니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; -// } elseif($city['supply'] == 0) { -// $log[] = "●{$admin['month']}월:고립된 도시입니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; - } elseif(!$nearCity) { - $log[] = "●{$admin['month']}월:인접도시가 아닙니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; - } elseif($general['level'] == 0) { - $log[] = "●{$admin['month']}월:재야입니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; - } elseif($general['crew'] <= 0) { - $log[] = "●{$admin['month']}월:병사가 없습니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; - } elseif($general['rice'] <= Util::round($general['crew']/100)) { - $log[] = "●{$admin['month']}월:군량이 모자랍니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; - } elseif($dip['state'] != 0) { - $log[] = "●{$admin['month']}월:교전중인 국가가 아닙니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; - } elseif($general['nation'] != $city['nation']) { - $log[] = "●{$admin['month']}월:본국에서만 출병가능합니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; - } elseif($nation['war'] == 1) { - $log[] = "●{$admin['month']}월:현재 전쟁 금지입니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; - } elseif($general['nation'] == $destcity['nation']) { - $log[] = "●{$admin['month']}월:본국입니다. {$destcity['name']}{$josaRo} 출병 실패. <1>$date"; + $log[] = "●{$admin['month']}월:현재 초반 제한중입니다. {$finalDestCityName} 방향으로 출병 실패. <1>$date"; + pushGenLog($general, $log); + return; + } + + if($general['level'] == 0) { + $log[] = "●{$admin['month']}월:재야입니다. {$finalDestCityName} 방향으로 출병 실패. <1>$date"; + pushGenLog($general, $log); + return; + } + if($general['crew'] <= 0) { + $log[] = "●{$admin['month']}월:병사가 없습니다. {$finalDestCityName} 방향으로 출병 실패. <1>$date"; + pushGenLog($general, $log); + return; + } + + if($general['rice'] <= Util::round($general['crew']/100)) { + $log[] = "●{$admin['month']}월:군량이 모자랍니다. {$finalDestCityName} 방향으로 출병 실패. <1>$date"; + pushGenLog($general, $log); + return; + } + + if($nation['war'] == 1) { + $log[] = "●{$admin['month']}월:현재 전쟁 금지입니다. {$finalDestCityName} 방향으로 출병 실패. <1>$date"; + pushGenLog($general, $log); + return; + } + + if($general['nation'] != $city['nation']) { + $log[] = "●{$admin['month']}월:본국에서만 출병가능합니다. {$finalDestCityName} 방향으로 출병 실패. <1>$date"; + pushGenLog($general, $log); + return; + } + + if($general['city'] == $finalTarget){ + $log[] = "●{$admin['month']}월:이미 도착했습니다. {$finalDestCityName} 방향으로 출병 실패. <1>$date"; + pushGenLog($general, $log); + return; + } + + + $allowedNationList = $db->queryFirstColumn('SELECT you FROM diplomacy WHERE state = 0 AND me = %i', $general['nation']); + $allowedNationList[] = $general['nation']; + + $distanceList = searchDistanceListToDest($general['city'], $finalTarget, $allowedNationList); + + if(!$distanceList){ + $log[] = "●{$admin['month']}월:경로에 도달할 방법이 없습니다. {$finalDestCityName} 방향으로 출병 실패. <1>$date"; + pushGenLog($general, $log); + return; + } + + $candidateCities = []; + + $minDist = array_key_first($distanceList); + do { + //1: 최단 거리 도시 중 공격 대상이 있는가 확인 + //2: 최단 거리 + 1 도시 중 공격 대상이 있는가 확인 + foreach($distanceList as $dist => $distCitiesInfo){ + if($dist > $minDist + 1){ + break; + } + $currDist = $dist; + foreach($distCitiesInfo as [$distCityID, $distCityNation]){ + if($distCityNation !== $general['nation']){ + $candidateCities[] = $distCityID; + } + } + + if($candidateCities){ + break 2; + } + } + + //3: 최단 거리 도시 중 아군 도시 선택 + foreach($distanceList[$minDist] as [$distCityID, $distCityNation]){ + if($distCityNation === $general['nation']){ + $candidateCities[] = $distCityID; + } + } + }while(false); + + $destCityID = (int)Util::choiceRandom($candidateCities); + $destCity = $db->queryFirstRow('SELECT * FROM city WHERE city = %i', $destCityID); + + if($general['nation'] == $destCity['nation']) { + $log[] = "●{$admin['month']}월:경로에 적국 도시가 없습니다. {$finalDestCityName} 방향으로 출병 실패. <1>$date"; + $general['turn0'] = EncodeCommand(0, 0, $destCityID, 26); pushGenLog($general, $log); process_21($general); return; - } else { - // 전쟁 표시 - $query = "update city set state=43,term=3 where city='{$destcity['city']}'"; - MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); - // 숙련도 증가 - addGenDex($general['no'], GameConst::$maxAtmosByCommand, GameConst::$maxTrainByCommand, $general['crewtype'], Util::round($general['crew']/100)); - // 전투 처리 - processWar($general, $destcity); - $log = uniqueItem($general, $log); } + $destCityName = CityConst::byID($destCityID)->name; + if($finalTarget !== $destCityID){ + $josaRo = JosaUtil::pick($finalDestCityName, '로'); + $josaUl = JosaUtil::pick($destCityName, '을'); + if($minDist == $currDist){ + $log[] = "●{$admin['month']}월:{$finalDestCityName}{$josaRo} 가기 위해 {$destCityName}{$josaUl} 거쳐야 합니다. <1>$date"; + } + else{ + $log[] = "●{$admin['month']}월:{$finalDestCityName}{$josaRo} 가는 도중 {$destCityName}{$josaUl} 거치기로 합니다. <1>$date"; + } + + pushGenLog($general, $log); + $log = []; + } + + // 전쟁 표시 + $db->update('city', [ + 'state'=>43, + 'term'=>3 + ], 'city = %i', $destCityID); + // 숙련도 증가 + addGenDex($general['no'], GameConst::$maxAtmosByCommand, GameConst::$maxTrainByCommand, $general['crewtype'], Util::round($general['crew']/100)); + // 전투 처리 + processWar($general, $destCity); + $log = uniqueItem($general, $log); + pushGenLog($general, $log); } diff --git a/hwe/processing.php b/hwe/processing.php index 444fe712..92474c3f 100644 --- a/hwe/processing.php +++ b/hwe/processing.php @@ -392,7 +392,8 @@ function command_16($turn, $command) { echo getMapHtml(); echo "
-선택된 도시로 침공을 합니다.
+선택된 도시를 향해 침공을 합니다.
+침공 경로에 적군의 도시가 있다면 전투를 벌입니다.
목록을 선택하거나 도시를 클릭하세요.
{$currentcity['name']} => diff --git a/index.php b/index.php index dc846ccb..746fe118 100644 --- a/index.php +++ b/index.php @@ -196,7 +196,7 @@ function postOAuthResult(result){
-
개인정보처리방침 & 이용약관
© 2019 • HideD +
개인정보처리방침 & 이용약관
© 2020 • HideD
크롬과 파이어폭스에 최적화되어있습니다.