Add: Handling of town cargoes in challenge creation.
This commit is contained in:
168
main.nut
168
main.nut
@@ -21,6 +21,81 @@ function FMainClass::ExamineCargoes()
|
||||
}
|
||||
}
|
||||
|
||||
// Find cargo sources.
|
||||
// @param cargo_id Cargo index (index in this.cargoes).
|
||||
// @return List of resources that produce the requested cargo, list of
|
||||
// 'ind' or 'town' number, 'prod' produced amount, 'transp' transported amount, and 'loc' location.
|
||||
function FMainClass::FindSources(cargo_id)
|
||||
{
|
||||
local cargo = this.cargoes[cargo_id];
|
||||
local num_sources = 0;
|
||||
local sources = {};
|
||||
|
||||
if (cargo.freight) {
|
||||
// For 'freight' cargoes, check the producing industries for sufficient available production.
|
||||
foreach (ind, _ in GSIndustryList_CargoProducing(cargo.cid)) {
|
||||
local prod_amount = GSIndustry.GetLastMonthProduction(ind, cargo.cid);
|
||||
if (prod_amount < 10) continue;
|
||||
local transp_amount = GSIndustry.GetLastMonthTransported(ind, cargo.cid);
|
||||
if (prod_amount - transp_amount < 10) continue;
|
||||
local loc = GSIndustry.GetLocation(ind);
|
||||
sources[num_sources] <- {ind=ind, prod=prod_amount, transp=transp_amount, loc=loc};
|
||||
num_sources += 1;
|
||||
}
|
||||
}
|
||||
if (cargo.effect != GSCargo.TE_NONE) {
|
||||
// For 'town effect' cargoes, check the towns for sufficient available production.
|
||||
foreach (town, _ in GSTownList()) {
|
||||
local prod_amount = GSTown.GetLastMonthProduction(town, cargo.cid);
|
||||
if (prod_amount < 10) continue;
|
||||
local transp_amount = GSTown.GetLastMonthSupplied(town, cargo.cid);
|
||||
if (prod_amount - transp_amount < 10) continue;
|
||||
local loc = GSTown.GetLocation(town);
|
||||
sources[num_sources] <- {town=town, prod=prod_amount, transp=transp_amount, loc=loc};
|
||||
num_sources += 1;
|
||||
}
|
||||
}
|
||||
return sources;
|
||||
}
|
||||
|
||||
// Find destinations for the cargo.
|
||||
// @param cargo_id Cargo index (index in this.cargoes).
|
||||
// @param company Company to inspect.
|
||||
// @return A list of destinations, tables 'ind' or 'town' id, and a 'loc' location.
|
||||
function FMainClass::FindDestinations(cargo_id, company)
|
||||
{
|
||||
local cargo = this.cargoes[cargo_id];
|
||||
local num_dests = 0;
|
||||
local dests = {};
|
||||
|
||||
if (cargo.freight) {
|
||||
// Assume all industries are willing to accept the cargo.
|
||||
foreach (ind, _ in GSIndustryList_CargoAccepting(cargo.cid)) {
|
||||
local loc = GSIndustry.GetLocation(ind);
|
||||
dests[num_dests] <- {ind=ind, loc=loc};
|
||||
num_dests += 1;
|
||||
}
|
||||
}
|
||||
if (cargo.effect != GSCargo.TE_NONE) {
|
||||
// Find towns with sufficient rating.
|
||||
local acceptable_ratings = [
|
||||
GSTown.TOWN_RATING_MEDIOCRE, GSTown.TOWN_RATING_GOOD,
|
||||
GSTown.TOWN_RATING_VERY_GOOD, GSTown.TOWN_RATING_EXCELLENT,
|
||||
GSTown.TOWN_RATING_OUTSTANDING, GSTown.TOWN_RATING_INVALID
|
||||
];
|
||||
|
||||
foreach (town, _ in GSTownList()) {
|
||||
local rating = GSTown.GetRating(town, company);
|
||||
if (rating in acceptable_ratings) {
|
||||
local loc = GSTown.GetLocation(town);
|
||||
dests[num_dests] <- {town=town, loc=loc};
|
||||
num_dests += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dests;
|
||||
}
|
||||
|
||||
// Construct a score for the distance
|
||||
// @param desired Desired distance.
|
||||
// @param actual Actual distance.
|
||||
@@ -34,81 +109,66 @@ function FMainClass::GetDistanceScore(desired, actual)
|
||||
// Try to find a challenge for a given cargo and a desired distance.
|
||||
// @param cargo Cargo entry from FMainClass.cargoes (table with 'cid', 'freight', 'effect').
|
||||
// @param distance Desired distance between source and target.
|
||||
// @param company Company to find a challenge for.
|
||||
// @return Best accepting industry to use, or 'null' if no industry-pair found.
|
||||
function FMainClass::FindChallenge(cargo, distance)
|
||||
function FMainClass::FindChallenge(cargo_id, distance, company)
|
||||
{
|
||||
if (cargo.freight) {
|
||||
local prod_inds = GSIndustryList_CargoProducing(cargo.cid); // Cache the list of producers.
|
||||
local prods = this.FindSources(cargo_id);
|
||||
local accepts = this.FindDestinations(cargo_id, company);
|
||||
|
||||
local best_score = 0; // Best overall distance.
|
||||
local best_accept_ind = null; // Best industry to target.
|
||||
foreach (accept_ind, _ in GSIndustryList_CargoAccepting(cargo.cid)) {
|
||||
local accept_tile = GSIndustry.GetLocation(accept_ind);
|
||||
local best_score = 0; // Best overall distance.
|
||||
local best_accept = null; // Best accepting to target.
|
||||
foreach (_, accept in accepts) {
|
||||
local min_prod_distance = distance * 2; // Smallest found distance to the accepting industry.
|
||||
local prod_score = GetDistanceScore(distance, min_prod_distance);
|
||||
foreach (_, prod in prods) {
|
||||
local actual_dist = GSTile.GetDistanceManhattanToTile(accept.loc, prod.loc);
|
||||
if (actual_dist > distance * 2) continue; // Too far away, skip.
|
||||
|
||||
local min_prod_distance = distance * 2; // Smallest found distance to the accepting industry.
|
||||
local prod_score = GetDistanceScore(distance, min_prod_distance);
|
||||
foreach (prod_ind, _ in prod_inds) {
|
||||
if (prod_ind == accept_ind) continue;
|
||||
local actual_dist = GSIndustry.GetDistanceManhattanToTile(prod_ind, accept_tile);
|
||||
if (actual_dist > distance * 2) continue; // Too far away, skip.
|
||||
|
||||
if (actual_dist < min_prod_distance) {
|
||||
min_prod_distance = actual_dist;
|
||||
prod_score = this.GetDistanceScore(distance, min_prod_distance);
|
||||
if (min_prod_distance < distance && prod_score < best_score) break;
|
||||
}
|
||||
}
|
||||
if (prod_score > best_score) { // The accepting industry is better than what we have.
|
||||
prod_score = best_score;
|
||||
best_accept_ind = accept_ind;
|
||||
if (actual_dist < min_prod_distance) {
|
||||
min_prod_distance = actual_dist;
|
||||
prod_score = this.GetDistanceScore(distance, min_prod_distance);
|
||||
if (min_prod_distance < distance && prod_score < best_score) break;
|
||||
}
|
||||
}
|
||||
return best_accept_ind;
|
||||
if (prod_score > best_score) { // The accepting industry is better than what we have.
|
||||
prod_score = best_score;
|
||||
best_accept = accept;
|
||||
}
|
||||
}
|
||||
return null; // XXX Town stuff not implemented yet.
|
||||
return best_accept;
|
||||
}
|
||||
|
||||
function FMainClass::Start()
|
||||
{
|
||||
// Wait for the game to start
|
||||
this.Sleep(1);
|
||||
this.Sleep(1); // Wait for the game to start.
|
||||
|
||||
this.ExamineCargoes();
|
||||
|
||||
// foreach(idx, val in cargoes) {
|
||||
// GSLog.Info(idx + " : " + GSCargo.GetCargoLabel(val.cid) + ", " + val.cid + ", " + val.freight + ", " + val.effect);
|
||||
// }
|
||||
local accept = FindChallenge(0, 50, GSCompany.COMPANY_FIRST); // Mail challenge
|
||||
if (accept != null) {
|
||||
if ("town" in accept) {
|
||||
GSLog.Info("Use town " + GSTown.GetName(accept.town));
|
||||
} else {
|
||||
GSLog.Info("Use industry " + GSIndustry.GetName(accept.ind));
|
||||
}
|
||||
}
|
||||
|
||||
local accept_ind = FindChallenge(cargoes[3], 50);
|
||||
if (accept_ind != null) {
|
||||
GSLog.Info("Use " + GSIndustry.GetName(accept_ind));
|
||||
local accept = FindChallenge(3, 50, GSCompany.COMPANY_FIRST); // Mail challenge
|
||||
if (accept != null) {
|
||||
if ("town" in accept) {
|
||||
GSLog.Info("Use town " + GSTown.GetName(accept.town));
|
||||
} else {
|
||||
GSLog.Info("Use industry " + GSIndustry.GetName(accept.ind));
|
||||
}
|
||||
}
|
||||
|
||||
// this is proof of concept only
|
||||
for (local cid = GSCompany.COMPANY_FIRST; cid < GSCompany.COMPANY_LAST; cid++) {
|
||||
for (local cid = GSCompany.COMPANY_FIRST; cid <= GSCompany.COMPANY_LAST; cid++) {
|
||||
GSLog.Info(cid);
|
||||
GSGoal.New(cid, "Foo", GSGoal.GT_NONE, 0);
|
||||
}
|
||||
|
||||
// for (local cid = 0; cid < 32; cid += 1) {
|
||||
// if (!GSCargo.IsValidCargo(cid)) continue;
|
||||
// local label = cid + " (" + GSCargo.GetCargoLabel(cid) + ")"
|
||||
// if (GSCargo.IsFreight(cid)) {
|
||||
// GSLog.Info(label + " is freight.");
|
||||
// local accept_inds = GSIndustryList_CargoAccepting(cid);
|
||||
// local prod_inds = GSIndustryList_CargoProducing(cid);
|
||||
// foreach (industry,_ in prod_inds) {
|
||||
// GSLog.Info("Produces " + label + " @ " + GSIndustry.GetName(industry));
|
||||
// }
|
||||
// foreach (industry,_ in accept_inds) {
|
||||
// GSLog.Info("Accepts " + label + " @ " + GSIndustry.GetName(industry));
|
||||
// }
|
||||
// } else if (GSCargo.GetTownEffect(cid) != GSCargo.TE_NONE) {
|
||||
// GSLog.Info(label + " affects town.");
|
||||
// } else {
|
||||
// GSLog.Info(label + " does nothing.");
|
||||
// }
|
||||
// }
|
||||
|
||||
while (true) {
|
||||
local lake_news = GSText(GSText.STR_LAKE_NEWS);
|
||||
if (GSBase.Chance(1, 5)) {
|
||||
|
||||
Reference in New Issue
Block a user