From 2f6b3310a7c4266268e810191a6b1ab0eaad4534 Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 26 Feb 2024 20:15:28 +0100 Subject: [PATCH 1/2] Add a couple more tests around accessing BOOSTS --- dist/screeps-tests.ts | 159 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 158 insertions(+), 1 deletion(-) diff --git a/dist/screeps-tests.ts b/dist/screeps-tests.ts index ef86142..39eddc9 100644 --- a/dist/screeps-tests.ts +++ b/dist/screeps-tests.ts @@ -1020,8 +1020,165 @@ function resources(o: GenericStore): ResourceConstant[] { EXTENSION_ENERGY_CAPACITY[Game.rooms.myRoom.controller!.level]; REACTIONS[Object.keys(creep.carry)[0]]; +} + +{ + // Test the BOOSTS constant + + // Can be used with a body part, returns a record of mineral -> boosted property -> level + const c = BOOSTS[creep.body[0].type]; + + // Can be used with all body part types, returns undefined + const undef = BOOSTS["claim"]; + + // Can still be iterated over + for (const bodyPart of Object.keys(BOOSTS) as BodyPartConstant[]) { + const boosts = BOOSTS[bodyPart]; + for (const mineral of Object.keys(boosts) as MineralBoostConstant[]) { + const upgrades = boosts[mineral]; + } + } +} - BOOSTS[creep.body[0].type]; +{ + // Boost estimation code lifted from Overmind + + type HARVEST = "harvest"; + type CONSTRUCT = "construct"; + type DISMANTLE = "dismantle"; + type UPGRADE = "upgrade"; + const HARVEST: HARVEST = "harvest"; + const CONSTRUCT: CONSTRUCT = "construct"; + const DISMANTLE: DISMANTLE = "dismantle"; + const UPGRADE: UPGRADE = "upgrade"; + + type BoostTier = "T1" | "T2" | "T3"; + type BoostType = ATTACK | CARRY | RANGED_ATTACK | HEAL | MOVE | TOUGH | HARVEST | CONSTRUCT | DISMANTLE | UPGRADE; + + const BOOST_TIERS: { + [boostType in BoostType]: { + [boostTier in BoostTier]: MineralBoostConstant; + }; + } = { + attack: { + T1: "UH", + T2: "UH2O", + T3: "XUH2O", + }, + carry: { + T1: "KH", + T2: "KH2O", + T3: "XKH2O", + }, + ranged_attack: { + T1: "KO", + T2: "KHO2", + T3: "XKHO2", + }, + heal: { + T1: "LO", + T2: "LHO2", + T3: "XLHO2", + }, + move: { + T1: "ZO", + T2: "ZHO2", + T3: "XZHO2", + }, + tough: { + T1: "GO", + T2: "GHO2", + T3: "XGHO2", + }, + harvest: { + T1: "UO", + T2: "UHO2", + T3: "XUHO2", + }, + construct: { + T1: "LH", + T2: "LH2O", + T3: "XLH2O", + }, + dismantle: { + T1: "ZH", + T2: "ZH2O", + T3: "XZH2O", + }, + upgrade: { + T1: "GH", + T2: "GH2O", + T3: "XGH2O", + }, + }; + + const BoostTypeBodyparts: { + [boostType in BoostType]: BodyPartConstant; + } = { + [ATTACK]: ATTACK, + [CARRY]: CARRY, + [RANGED_ATTACK]: RANGED_ATTACK, + [HEAL]: HEAL, + [MOVE]: MOVE, + [TOUGH]: TOUGH, + [HARVEST]: WORK, + [CONSTRUCT]: WORK, + [DISMANTLE]: WORK, + [UPGRADE]: WORK, + }; + + const BoostTypeToBoostArray: { + [boostType in BoostType]: BoostModifier; + } = { + [ATTACK]: ATTACK, + [CARRY]: "capacity", + [RANGED_ATTACK]: "rangedAttack", + // [RANGED_MASS_ATTACK]: "rangedMassAttack", + [HEAL]: HEAL, + [MOVE]: "fatigue", + [TOUGH]: "damage", + [HARVEST]: "harvest", + [CONSTRUCT]: "build", + // [REPAIR]: "repair", + [DISMANTLE]: "dismantle", + [UPGRADE]: "upgradeController", + }; + + /** + * + * @param body + * @param type + * @param intendedBoosts + * @returns + */ + function getBodyPotential(body: BodyPartDefinition[], type: BoostType, intendedBoosts: MineralBoostConstant[] = []): number { + const bodyPart = BoostTypeBodyparts[type]; + return body.reduce((sum, part) => { + if (part.hits === 0) { + return sum + 0; + } + if (part.type === bodyPart) { + let boost = part.boost; + if (!boost && intendedBoosts) { + boost = intendedBoosts.find( + (boost) => boost === BOOST_TIERS[type].T1 || boost === BOOST_TIERS[type].T2 || boost === BOOST_TIERS[type].T3, + ); + } + if (!boost) { + return sum + 1; + } + + const key = BoostTypeToBoostArray[type]; + const partBoost = BOOSTS[bodyPart]; + if (!partBoost || !(boost in partBoost) || !partBoost[boost] || !(key in partBoost[boost])) { + return sum + 0; + } + + return partBoost[boost][key]; + } + return sum + 0; + }, 0); + } } // Tombstones From 549f9ef5f26b5e503e84f817eb95f572d3beba0d Mon Sep 17 00:00:00 2001 From: Etienne Samson Date: Mon, 26 Feb 2024 21:06:19 +0100 Subject: [PATCH 2/2] Provide a more type-correct overlay over BOOSTS --- dist/index.d.ts | 20 +++++++++++++++++--- dist/screeps-tests.ts | 2 +- src/constants.ts | 3 +-- src/helpers.ts | 2 +- src/literals.ts | 15 +++++++++++++++ 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/dist/index.d.ts b/dist/index.d.ts index 235139f..cf17cb6 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -608,7 +608,6 @@ declare const REACTION_TIME: { }; declare const BOOSTS: { - [part: string]: { [boost: string]: { [action: string]: number } }; work: { UO: { harvest: 3; @@ -722,7 +721,7 @@ declare const BOOSTS: { damage: 0.3; }; }; -}; +} & Record>>; declare const INTERSHARD_RESOURCES: InterShardResourceConstant[]; @@ -1729,7 +1728,7 @@ type BodyPartDefinition = T exten * * If the body part is boosted, this property specifies the mineral type which is used for boosting. */ - boost?: keyof (typeof BOOSTS)[T]; + boost?: keyof typeof BOOSTS[T]; /** * One of the body part types constants. */ @@ -2733,6 +2732,21 @@ type EffectConstant = EFFECT_INVULNERABILITY | EFFECT_COLLAPSE_TIMER; type EFFECT_INVULNERABILITY = 1001; type EFFECT_COLLAPSE_TIMER = 1002; + +type BoostModifier = + | "harvest" + | "build" + | "repair" + | "dismantle" + | "upgradeController" + | "attack" + | "rangedAttack" + | "rangedMassAttack" + | "heal" + | "rangedHeal" + | "capacity" + | "fatigue" + | "damage"; /** * The options that can be accepted by `findRoute()` and friends. */ diff --git a/dist/screeps-tests.ts b/dist/screeps-tests.ts index 39eddc9..97cf162 100644 --- a/dist/screeps-tests.ts +++ b/dist/screeps-tests.ts @@ -1332,7 +1332,7 @@ function atackPower(creep: Creep) { return creep.body .map((part) => { if (part.type === ATTACK) { - const multiplier = part.boost ? BOOSTS[part.type][part.boost].attack : 1; + const multiplier = part.boost ? BOOSTS[part.type][part.boost]?.attack ?? 0 : 1; return multiplier * ATTACK_POWER; } return 0; diff --git a/src/constants.ts b/src/constants.ts index d679266..64316c0 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -608,7 +608,6 @@ declare const REACTION_TIME: { }; declare const BOOSTS: { - [part: string]: { [boost: string]: { [action: string]: number } }; work: { UO: { harvest: 3; @@ -722,7 +721,7 @@ declare const BOOSTS: { damage: 0.3; }; }; -}; +} & Record>>; declare const INTERSHARD_RESOURCES: InterShardResourceConstant[]; diff --git a/src/helpers.ts b/src/helpers.ts index cb54a53..9bd3867 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -147,7 +147,7 @@ type BodyPartDefinition = T exten * * If the body part is boosted, this property specifies the mineral type which is used for boosting. */ - boost?: keyof (typeof BOOSTS)[T]; + boost?: keyof typeof BOOSTS[T]; /** * One of the body part types constants. */ diff --git a/src/literals.ts b/src/literals.ts index c0b36a5..984846c 100644 --- a/src/literals.ts +++ b/src/literals.ts @@ -698,3 +698,18 @@ type EffectConstant = EFFECT_INVULNERABILITY | EFFECT_COLLAPSE_TIMER; type EFFECT_INVULNERABILITY = 1001; type EFFECT_COLLAPSE_TIMER = 1002; + +type BoostModifier = + | "harvest" + | "build" + | "repair" + | "dismantle" + | "upgradeController" + | "attack" + | "rangedAttack" + | "rangedMassAttack" + | "heal" + | "rangedHeal" + | "capacity" + | "fatigue" + | "damage";