@umang-boss/claudemon 2.1.3 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/award-xp.mjs +129 -58
- package/dist/award-xp.mjs.map +3 -3
- package/dist/server.mjs +492 -99
- package/dist/server.mjs.map +2 -2
- package/package.json +1 -1
- package/src/engine/encounter-pool.ts +51 -6
- package/src/engine/encounters.ts +122 -128
- package/src/gamification/legendary-quests.ts +515 -91
- package/src/hooks/award-xp.ts +3 -5
package/dist/award-xp.mjs
CHANGED
|
@@ -75,6 +75,26 @@ import { constants as fsConst } from "node:fs";
|
|
|
75
75
|
|
|
76
76
|
// src/engine/types.ts
|
|
77
77
|
var MOOD_TYPES = ["happy", "worried", "sleepy", "energetic", "proud", "neutral"];
|
|
78
|
+
var POKEMON_TYPES = [
|
|
79
|
+
"Normal",
|
|
80
|
+
"Fire",
|
|
81
|
+
"Water",
|
|
82
|
+
"Electric",
|
|
83
|
+
"Grass",
|
|
84
|
+
"Ice",
|
|
85
|
+
"Fighting",
|
|
86
|
+
"Poison",
|
|
87
|
+
"Ground",
|
|
88
|
+
"Flying",
|
|
89
|
+
"Psychic",
|
|
90
|
+
"Bug",
|
|
91
|
+
"Rock",
|
|
92
|
+
"Ghost",
|
|
93
|
+
"Dragon",
|
|
94
|
+
"Steel",
|
|
95
|
+
"Dark",
|
|
96
|
+
"Fairy"
|
|
97
|
+
];
|
|
78
98
|
var CODING_STATS = ["stamina", "debugging", "stability", "velocity", "wisdom"];
|
|
79
99
|
var BADGE_TYPES = [
|
|
80
100
|
"blaze",
|
|
@@ -16435,6 +16455,40 @@ function isBaseStage(pokemonId) {
|
|
|
16435
16455
|
return !EVOLVED_IDS.has(pokemonId);
|
|
16436
16456
|
}
|
|
16437
16457
|
var WILD_RARITIES = /* @__PURE__ */ new Set(["common", "uncommon", "rare"]);
|
|
16458
|
+
var GEN_RANGES = [
|
|
16459
|
+
{ gen: 1, start: 1, end: 151 },
|
|
16460
|
+
{ gen: 2, start: 152, end: 251 },
|
|
16461
|
+
{ gen: 3, start: 252, end: 386 },
|
|
16462
|
+
{ gen: 4, start: 387, end: 493 },
|
|
16463
|
+
{ gen: 5, start: 494, end: 649 },
|
|
16464
|
+
{ gen: 6, start: 650, end: 721 },
|
|
16465
|
+
{ gen: 7, start: 722, end: 809 },
|
|
16466
|
+
{ gen: 8, start: 810, end: 905 }
|
|
16467
|
+
];
|
|
16468
|
+
function getGeneration(pokemonId) {
|
|
16469
|
+
for (const { gen, start, end } of GEN_RANGES) {
|
|
16470
|
+
if (pokemonId >= start && pokemonId <= end) return gen;
|
|
16471
|
+
}
|
|
16472
|
+
return 1;
|
|
16473
|
+
}
|
|
16474
|
+
function buildAllPool() {
|
|
16475
|
+
const common = [];
|
|
16476
|
+
const uncommon = [];
|
|
16477
|
+
const rare = [];
|
|
16478
|
+
for (const pokemon2 of POKEDEX) {
|
|
16479
|
+
if (!isBaseStage(pokemon2.id)) continue;
|
|
16480
|
+
if (!WILD_RARITIES.has(pokemon2.rarity)) continue;
|
|
16481
|
+
const rarity = pokemon2.rarity;
|
|
16482
|
+
if (rarity === "common") common.push(pokemon2.id);
|
|
16483
|
+
else if (rarity === "uncommon") uncommon.push(pokemon2.id);
|
|
16484
|
+
else rare.push(pokemon2.id);
|
|
16485
|
+
}
|
|
16486
|
+
return {
|
|
16487
|
+
common: Object.freeze(common),
|
|
16488
|
+
uncommon: Object.freeze(uncommon),
|
|
16489
|
+
rare: Object.freeze(rare)
|
|
16490
|
+
};
|
|
16491
|
+
}
|
|
16438
16492
|
function buildTypePools() {
|
|
16439
16493
|
const pools = /* @__PURE__ */ new Map();
|
|
16440
16494
|
for (const pokemon2 of POKEDEX) {
|
|
@@ -16462,32 +16516,14 @@ function buildTypePools() {
|
|
|
16462
16516
|
return frozen;
|
|
16463
16517
|
}
|
|
16464
16518
|
var TYPE_POOLS = buildTypePools();
|
|
16519
|
+
var ALL_WILD_POOL = buildAllPool();
|
|
16465
16520
|
|
|
16466
16521
|
// src/engine/encounters.ts
|
|
16467
|
-
var ENCOUNTER_TYPE_MAP = {
|
|
16468
|
-
commit: ["Normal", "Flying"],
|
|
16469
|
-
test_pass: ["Fighting", "Normal"],
|
|
16470
|
-
test_written: ["Fighting", "Normal"],
|
|
16471
|
-
build_success: ["Fire", "Rock"],
|
|
16472
|
-
bug_fix: ["Bug", "Poison"],
|
|
16473
|
-
lint_fix: ["Bug", "Poison"],
|
|
16474
|
-
file_create: ["Normal", "Ground"],
|
|
16475
|
-
file_edit: ["Normal", "Ground"],
|
|
16476
|
-
search: ["Flying", "Ground"],
|
|
16477
|
-
large_refactor: ["Psychic", "Dragon"],
|
|
16478
|
-
session_start: ["Grass", "Fairy"],
|
|
16479
|
-
daily_streak: ["Water", "Electric"],
|
|
16480
|
-
pet: ["Normal", "Fairy"]
|
|
16481
|
-
};
|
|
16482
|
-
function getEncounterTypes(eventType2) {
|
|
16483
|
-
return ENCOUNTER_TYPE_MAP[eventType2];
|
|
16484
|
-
}
|
|
16485
16522
|
function shouldTriggerEncounter(ctx) {
|
|
16486
16523
|
const threshold = ENCOUNTER_THRESHOLDS[ctx.encounterSpeed];
|
|
16487
16524
|
const streakMultiplier = ctx.currentStreak >= 7 ? 0.5 : 1;
|
|
16488
16525
|
const effectiveThreshold = Math.floor(threshold * streakMultiplier);
|
|
16489
|
-
|
|
16490
|
-
return true;
|
|
16526
|
+
return ctx.xpSinceLastEncounter >= effectiveThreshold;
|
|
16491
16527
|
}
|
|
16492
16528
|
function shouldBonusEncounter() {
|
|
16493
16529
|
return Math.random() < 0.1;
|
|
@@ -16496,13 +16532,6 @@ function shouldDiversityBonus(recentToolTypes2) {
|
|
|
16496
16532
|
const uniqueTypes = new Set(recentToolTypes2);
|
|
16497
16533
|
return uniqueTypes.size >= 3;
|
|
16498
16534
|
}
|
|
16499
|
-
function getTimeOfDayBias(hour) {
|
|
16500
|
-
if (hour >= 22 || hour < 5) return ["Ghost", "Dark"];
|
|
16501
|
-
if (hour >= 5 && hour < 9) return ["Grass", "Fairy"];
|
|
16502
|
-
if (hour >= 12 && hour < 14) return ["Fire", "Steel"];
|
|
16503
|
-
if (hour >= 17 && hour < 20) return ["Water", "Flying"];
|
|
16504
|
-
return [];
|
|
16505
|
-
}
|
|
16506
16535
|
var RARITY_WEIGHTS = {
|
|
16507
16536
|
common: 70,
|
|
16508
16537
|
uncommon: 25,
|
|
@@ -16557,30 +16586,81 @@ function getCatchCondition(pokemonId) {
|
|
|
16557
16586
|
const requiredStat = TYPE_TO_STAT[primaryType];
|
|
16558
16587
|
return { requiredStat, minStatValue, requiredLevel };
|
|
16559
16588
|
}
|
|
16560
|
-
function
|
|
16589
|
+
function getTypeCounts(state2) {
|
|
16590
|
+
const counts = /* @__PURE__ */ new Map();
|
|
16591
|
+
for (const t of POKEMON_TYPES) counts.set(t, 0);
|
|
16592
|
+
for (const [idStr, entry] of Object.entries(state2.pokedex.entries)) {
|
|
16593
|
+
if (!entry.caught) continue;
|
|
16594
|
+
const pokemon2 = POKEMON_BY_ID.get(Number(idStr));
|
|
16595
|
+
if (!pokemon2) continue;
|
|
16596
|
+
for (const t of pokemon2.types) {
|
|
16597
|
+
if (t !== void 0) counts.set(t, (counts.get(t) ?? 0) + 1);
|
|
16598
|
+
}
|
|
16599
|
+
}
|
|
16600
|
+
return counts;
|
|
16601
|
+
}
|
|
16602
|
+
function getGenCounts(state2) {
|
|
16603
|
+
const counts = /* @__PURE__ */ new Map();
|
|
16604
|
+
for (const { gen } of GEN_RANGES) counts.set(gen, 0);
|
|
16605
|
+
for (const [idStr, entry] of Object.entries(state2.pokedex.entries)) {
|
|
16606
|
+
if (!entry.caught) continue;
|
|
16607
|
+
const gen = getGeneration(Number(idStr));
|
|
16608
|
+
counts.set(gen, (counts.get(gen) ?? 0) + 1);
|
|
16609
|
+
}
|
|
16610
|
+
return counts;
|
|
16611
|
+
}
|
|
16612
|
+
function buildSmartPool(state2) {
|
|
16561
16613
|
const candidates = [];
|
|
16562
|
-
const seen = /* @__PURE__ */ new Set();
|
|
16563
16614
|
const starterPokemon = [...state2.party, ...state2.pcBox].find((p) => p.isStarter);
|
|
16564
16615
|
const starterPokemonId = starterPokemon?.pokemonId ?? -1;
|
|
16565
16616
|
const caughtIds = /* @__PURE__ */ new Set();
|
|
16617
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
16566
16618
|
for (const [idStr, entry] of Object.entries(state2.pokedex.entries)) {
|
|
16567
|
-
|
|
16568
|
-
|
|
16569
|
-
|
|
16619
|
+
const id = Number(idStr);
|
|
16620
|
+
if (entry.caught) caughtIds.add(id);
|
|
16621
|
+
if (entry.seen) seenIds.add(id);
|
|
16570
16622
|
}
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
16574
|
-
|
|
16575
|
-
|
|
16576
|
-
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
|
|
16582
|
-
|
|
16623
|
+
const totalCaught = state2.pokedex.totalCaught ?? 0;
|
|
16624
|
+
const isEarlyGame = totalCaught < 50;
|
|
16625
|
+
const seed = Math.floor(Date.now() / 1e3);
|
|
16626
|
+
const sameAgainRoll = seededRandom(seed + 99);
|
|
16627
|
+
const applyDiversity = sameAgainRoll >= 0.1;
|
|
16628
|
+
let typeCounts = null;
|
|
16629
|
+
let genCounts = null;
|
|
16630
|
+
if (applyDiversity) {
|
|
16631
|
+
typeCounts = getTypeCounts(state2);
|
|
16632
|
+
genCounts = getGenCounts(state2);
|
|
16633
|
+
}
|
|
16634
|
+
for (const rarity of ["common", "uncommon", "rare"]) {
|
|
16635
|
+
const ids = ALL_WILD_POOL[rarity];
|
|
16636
|
+
const baseWeight = RARITY_WEIGHTS[rarity];
|
|
16637
|
+
for (const id of ids) {
|
|
16638
|
+
if (id === starterPokemonId) continue;
|
|
16639
|
+
if (rarity !== "common" && caughtIds.has(id)) continue;
|
|
16640
|
+
let weight = baseWeight;
|
|
16641
|
+
if (applyDiversity) {
|
|
16642
|
+
const pokemon2 = POKEMON_BY_ID.get(id);
|
|
16643
|
+
if (pokemon2) {
|
|
16644
|
+
if (!seenIds.has(id)) {
|
|
16645
|
+
weight *= isEarlyGame ? 4 : 2;
|
|
16646
|
+
}
|
|
16647
|
+
const primaryType = pokemon2.types[0];
|
|
16648
|
+
const typeCount = typeCounts.get(primaryType) ?? 0;
|
|
16649
|
+
if (typeCount === 0) {
|
|
16650
|
+
weight *= 3;
|
|
16651
|
+
} else if (typeCount < 3) {
|
|
16652
|
+
weight *= 1.5;
|
|
16653
|
+
}
|
|
16654
|
+
const gen = getGeneration(id);
|
|
16655
|
+
const genCount = genCounts.get(gen) ?? 0;
|
|
16656
|
+
if (genCount === 0) {
|
|
16657
|
+
weight *= 2;
|
|
16658
|
+
} else if (genCount < 3) {
|
|
16659
|
+
weight *= 1.3;
|
|
16660
|
+
}
|
|
16661
|
+
}
|
|
16583
16662
|
}
|
|
16663
|
+
candidates.push({ id, weight: Math.round(weight) });
|
|
16584
16664
|
}
|
|
16585
16665
|
}
|
|
16586
16666
|
return candidates;
|
|
@@ -16612,16 +16692,8 @@ function determineEncounterLevel(state2, seed) {
|
|
|
16612
16692
|
const level = minLevel + Math.floor(seededRandom(seed + 7) * range);
|
|
16613
16693
|
return Math.min(level, 100);
|
|
16614
16694
|
}
|
|
16615
|
-
function generateEncounter(
|
|
16616
|
-
|
|
16617
|
-
if (timeOfDayTypes2 && timeOfDayTypes2.length > 0) {
|
|
16618
|
-
const seed2 = Math.floor(Date.now() / 1e3);
|
|
16619
|
-
const biasRoll = seededRandom(seed2 + 42);
|
|
16620
|
-
if (biasRoll < 0.4) {
|
|
16621
|
-
types = timeOfDayTypes2;
|
|
16622
|
-
}
|
|
16623
|
-
}
|
|
16624
|
-
const candidates = buildCandidatePool(types, state2);
|
|
16695
|
+
function generateEncounter(_eventType, state2, _timeOfDayTypes) {
|
|
16696
|
+
const candidates = buildSmartPool(state2);
|
|
16625
16697
|
if (candidates.length === 0) return null;
|
|
16626
16698
|
const seed = Math.floor(Date.now() / 1e3);
|
|
16627
16699
|
const pokemonId = weightedSelect(candidates, seed);
|
|
@@ -16759,7 +16831,6 @@ for (const badge of newBadges) {
|
|
|
16759
16831
|
var evolutionReady = checkEvolution(pokemon, state) !== null;
|
|
16760
16832
|
var encounterSpeed = state.config.encounterSpeed ?? "normal";
|
|
16761
16833
|
var currentHour = (/* @__PURE__ */ new Date()).getHours();
|
|
16762
|
-
var timeOfDayTypes = getTimeOfDayBias(currentHour);
|
|
16763
16834
|
var encounterCtx = {
|
|
16764
16835
|
xpSinceLastEncounter: (state.xpSinceLastEncounter ?? 0) + xpEvent.xp,
|
|
16765
16836
|
encounterSpeed,
|
|
@@ -16770,14 +16841,14 @@ var encounterCtx = {
|
|
|
16770
16841
|
state.xpSinceLastEncounter = encounterCtx.xpSinceLastEncounter;
|
|
16771
16842
|
var encounterTriggered = false;
|
|
16772
16843
|
if (shouldTriggerEncounter(encounterCtx) && !state.pendingEncounter) {
|
|
16773
|
-
const encounter = generateEncounter(eventType, state
|
|
16844
|
+
const encounter = generateEncounter(eventType, state);
|
|
16774
16845
|
if (encounter) {
|
|
16775
16846
|
state.pendingEncounter = encounter;
|
|
16776
16847
|
state.xpSinceLastEncounter = 0;
|
|
16777
16848
|
state.lastEncounterTime = Date.now();
|
|
16778
16849
|
encounterTriggered = true;
|
|
16779
16850
|
if (shouldBonusEncounter()) {
|
|
16780
|
-
const bonusEncounter = generateEncounter(eventType, state
|
|
16851
|
+
const bonusEncounter = generateEncounter(eventType, state);
|
|
16781
16852
|
if (bonusEncounter) {
|
|
16782
16853
|
state.pendingEncounter = bonusEncounter;
|
|
16783
16854
|
}
|
|
@@ -16785,7 +16856,7 @@ if (shouldTriggerEncounter(encounterCtx) && !state.pendingEncounter) {
|
|
|
16785
16856
|
}
|
|
16786
16857
|
}
|
|
16787
16858
|
if (!encounterTriggered && !state.pendingEncounter && shouldDiversityBonus(state.recentToolTypes)) {
|
|
16788
|
-
const diversityEncounter = generateEncounter(eventType, state
|
|
16859
|
+
const diversityEncounter = generateEncounter(eventType, state);
|
|
16789
16860
|
if (diversityEncounter) {
|
|
16790
16861
|
state.pendingEncounter = diversityEncounter;
|
|
16791
16862
|
state.xpSinceLastEncounter = 0;
|