Skip to content

Commit b38c8ea

Browse files
StopDragonclaude
andcommitted
fix: 골드채굴 모드 레벨 인식 버그 수정 (v2.5.4)
- 레벨 파싱 시 마지막 매칭 사용 (최신 채팅 값 사용) - ResultLevel 직접 사용으로 정확도 향상 - 기존 보유 검 세션 시작 시 보존 - 엔터 기본값을 최적 레벨(★)로 변경 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 1063837 commit b38c8ea

File tree

3 files changed

+108
-47
lines changed

3 files changed

+108
-47
lines changed

internal/game/engine.go

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,17 +252,19 @@ func (e *Engine) runGoldMineMode() {
252252
}
253253

254254
fmt.Println()
255-
fmt.Printf("목표 레벨 (엔터=%d): ", optimalLevel)
255+
// 최적 레벨(★)을 기본값으로 사용 (시간 효율 최대화)
256+
defaultTarget := optimalLevel
257+
fmt.Printf("목표 레벨 (엔터=%d): ", defaultTarget)
256258

257259
input, _ := reader.ReadString('\n')
258260
input = strings.TrimSpace(input)
259261

260262
if input == "" {
261-
e.targetLevel = optimalLevel
263+
e.targetLevel = defaultTarget
262264
} else if level, err := strconv.Atoi(input); err == nil && level >= 1 && level <= 20 {
263265
e.targetLevel = level
264266
} else {
265-
e.targetLevel = optimalLevel
267+
e.targetLevel = defaultTarget
266268
}
267269

268270
// 선택한 레벨의 효율성 정보 표시
@@ -853,6 +855,23 @@ func (e *Engine) loopGoldMine() {
853855
valid bool
854856
}
855857

858+
// 세션 시작 시 기존 보유 검 정보 (목표 미달이지만 0강 이상인 경우)
859+
var pendingExistingSword struct {
860+
name string
861+
itemType string
862+
level int
863+
valid bool
864+
}
865+
866+
// 세션 시작 시 이미 보유한 검이 있고, 목표 미달이면 바로 강화 이어가기
867+
if e.sessionProfile != nil && e.sessionProfile.Level > 0 && !e.IsTargetReached(e.sessionProfile.Level) {
868+
pendingExistingSword.name = e.sessionProfile.SwordName
869+
pendingExistingSword.itemType = DetermineItemType(e.sessionProfile.SwordName)
870+
pendingExistingSword.level = e.sessionProfile.Level
871+
pendingExistingSword.valid = true
872+
fmt.Printf("📋 기존 검 +%d 보유 중 → 목표 +%d까지 강화 이어가기\n", e.sessionProfile.Level, e.targetLevel)
873+
}
874+
856875
for e.running {
857876
if e.checkStop() {
858877
return
@@ -865,8 +884,16 @@ func (e *Engine) loopGoldMine() {
865884
var itemLevel int
866885
var found bool
867886

868-
// 이전 판매로 +0 검을 받았으면 farmForGoldMine 스킵
869-
if pendingZeroSword.valid {
887+
// 우선순위 1: 세션 시작 시 기존 보유 검 (목표 미달이지만 0강 이상)
888+
if pendingExistingSword.valid {
889+
itemName = pendingExistingSword.name
890+
itemType = pendingExistingSword.itemType
891+
itemLevel = pendingExistingSword.level
892+
found = true
893+
pendingExistingSword.valid = false // 사용 후 초기화
894+
fmt.Printf(" 📦 기존 보유 검 사용: %s +%d → 강화 이어가기\n", itemName, itemLevel)
895+
} else if pendingZeroSword.valid {
896+
// 우선순위 2: 이전 판매로 받은 +0 검
870897
itemName = pendingZeroSword.name
871898
itemType = pendingZeroSword.itemType
872899
itemLevel = 0

internal/game/helpers.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -134,20 +134,27 @@ func (e *Engine) EnhanceToTarget(itemName string, startLevel int) EnhanceResult
134134
}
135135

136136
// 레벨 업데이트 (강화 결과 기반)
137-
// 핵심: 파싱 실패해도 강화 결과(success/hold)로 레벨 추정
137+
// 핵심: ResultLevel("+X → +Y" 패턴에서 추출)이 가장 정확함
138+
138139
if state.LastResult == "success" {
139-
// 강화 성공 = 레벨 +1 (파싱 결과보다 이걸 우선 신뢰)
140-
currentLevel++
141-
fmt.Printf(" ⚔️ 강화 성공! +%d 도달\n", currentLevel)
140+
// 강화 성공 - ResultLevel 우선 사용 (가장 정확함)
141+
if state.ResultLevel > 0 {
142+
currentLevel = state.ResultLevel
143+
fmt.Printf(" ⚔️ 강화 성공! +%d 도달\n", currentLevel)
144+
} else {
145+
// ResultLevel 파싱 실패 시 fallback으로 +1
146+
currentLevel++
147+
fmt.Printf(" ⚔️ 강화 성공! +%d 도달 (계산값)\n", currentLevel)
148+
}
142149
} else if state.LastResult == "hold" {
143150
// 유지 = 레벨 변화 없음
144151
fmt.Printf(" 💫 강화 유지 (현재 +%d)\n", currentLevel)
152+
} else if state.LastResult == "destroy" {
153+
// 파괴는 위에서 처리됨, 여기 오면 안됨
154+
fmt.Printf(" [경고] destroy가 fallback에서 감지됨\n")
145155
} else {
146-
// 결과 불명확 시 파싱된 레벨 사용 (fallback)
147-
newLevel := e.ExtractCurrentLevel(state)
148-
if newLevel > currentLevel {
149-
currentLevel = newLevel
150-
}
156+
// 결과 불명확 - 레벨 변경 없이 재시도
157+
fmt.Printf(" ❓ 결과 불명확 (LastResult='%s') - 재시도\n", state.LastResult)
151158
}
152159

153160
// 골드 부족 체크
@@ -157,6 +164,14 @@ func (e *Engine) EnhanceToTarget(itemName string, startLevel int) EnhanceResult
157164
FormatGold(goldInfo.RequiredGold), FormatGold(goldInfo.RemainingGold))
158165
return EnhanceResult{FinalLevel: currentLevel, Success: false, Destroyed: false}
159166
}
167+
168+
}
169+
170+
// 루프 종료 시 상태 출력
171+
if currentLevel >= e.targetLevel {
172+
fmt.Printf(" ✅ 목표 달성! +%d (목표: +%d)\n", currentLevel, e.targetLevel)
173+
} else {
174+
fmt.Printf(" ⚠️ 목표 미달 종료: +%d (목표: +%d)\n", currentLevel, e.targetLevel)
160175
}
161176

162177
return EnhanceResult{

internal/game/parser.go

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -422,22 +422,31 @@ func ExtractLevel(text string) int {
422422

423423
// ExtractEnhanceResultLevel 강화 결과에서 변경 후 레벨 추출
424424
// "+0 → +1" 패턴에서 1을 추출, 또는 "획득 검: [+1]" 패턴에서 1을 추출
425+
// 여러 매칭이 있으면 마지막(가장 최신) 사용
425426
func ExtractEnhanceResultLevel(text string) int {
426-
// 1순위: "+0 → +1" 패턴에서 결과 레벨 추출
427-
if matches := enhanceLevelPattern.FindStringSubmatch(text); len(matches) > 2 {
428-
if level, err := strconv.Atoi(matches[2]); err == nil {
429-
if level >= MinLevel && level <= MaxLevel {
430-
return level
427+
// 1순위: "+0 → +1" 패턴에서 결과 레벨 추출 (마지막 매칭)
428+
allMatches := enhanceLevelPattern.FindAllStringSubmatch(text, -1)
429+
if len(allMatches) > 0 {
430+
matches := allMatches[len(allMatches)-1] // 마지막 매칭 사용
431+
if len(matches) > 2 {
432+
if level, err := strconv.Atoi(matches[2]); err == nil {
433+
if level >= MinLevel && level <= MaxLevel {
434+
return level
435+
}
431436
}
432437
}
433438
}
434439

435-
// 2순위: "획득 검: [+N]" 패턴에서 레벨 추출
440+
// 2순위: "획득 검: [+N]" 패턴에서 레벨 추출 (마지막 매칭)
436441
swordPattern := regexp.MustCompile(`획득\s*검:\s*\[\+?(\d+)\]`)
437-
if matches := swordPattern.FindStringSubmatch(text); len(matches) > 1 {
438-
if level, err := strconv.Atoi(matches[1]); err == nil {
439-
if level >= MinLevel && level <= MaxLevel {
440-
return level
442+
allSwordMatches := swordPattern.FindAllStringSubmatch(text, -1)
443+
if len(allSwordMatches) > 0 {
444+
matches := allSwordMatches[len(allSwordMatches)-1]
445+
if len(matches) > 1 {
446+
if level, err := strconv.Atoi(matches[1]); err == nil {
447+
if level >= MinLevel && level <= MaxLevel {
448+
return level
449+
}
441450
}
442451
}
443452
}
@@ -595,39 +604,49 @@ func ParseProfile(text string) *Profile {
595604
}
596605
}
597606

598-
// 골드 추출 (음수 불가)
599-
if matches := profileGoldPattern.FindStringSubmatch(text); len(matches) > 1 {
600-
goldStr := strings.ReplaceAll(matches[1], ",", "")
601-
if gold, err := strconv.Atoi(goldStr); err == nil {
602-
// 골드는 절대 음수가 될 수 없음
603-
if gold >= 0 {
604-
profile.Gold = gold
607+
// 골드 추출 (음수 불가) - 마지막 매칭 사용
608+
allGoldMatches := profileGoldPattern.FindAllStringSubmatch(text, -1)
609+
if len(allGoldMatches) > 0 {
610+
matches := allGoldMatches[len(allGoldMatches)-1]
611+
if len(matches) > 1 {
612+
goldStr := strings.ReplaceAll(matches[1], ",", "")
613+
if gold, err := strconv.Atoi(goldStr); err == nil {
614+
// 골드는 절대 음수가 될 수 없음
615+
if gold >= 0 {
616+
profile.Gold = gold
617+
}
605618
}
606619
}
607620
}
608621

609-
// 보유 검 추출 (레벨 + 이름)
610-
if matches := profileSwordPattern.FindStringSubmatch(text); len(matches) > 2 {
611-
levelStr := strings.TrimPrefix(matches[1], "+")
612-
if level, err := strconv.Atoi(levelStr); err == nil {
613-
profile.Level = level
622+
// 보유 검 추출 (레벨 + 이름) - 마지막 매칭 사용 (채팅에 여러 프로필 있을 수 있음)
623+
allSwordMatches := profileSwordPattern.FindAllStringSubmatch(text, -1)
624+
if len(allSwordMatches) > 0 {
625+
// 마지막 매칭 사용 (가장 최신 프로필)
626+
matches := allSwordMatches[len(allSwordMatches)-1]
627+
if len(matches) > 2 {
628+
levelStr := strings.TrimPrefix(matches[1], "+")
629+
if level, err := strconv.Atoi(levelStr); err == nil {
630+
profile.Level = level
631+
}
632+
profile.SwordName = strings.TrimSpace(matches[2])
614633
}
615-
profile.SwordName = strings.TrimSpace(matches[2])
616634
}
617635

618-
// 최고 기록 추출
619-
if matches := profileBestPattern.FindStringSubmatch(text); len(matches) > 2 {
620-
levelStr := strings.TrimPrefix(matches[1], "+")
621-
if level, err := strconv.Atoi(levelStr); err == nil {
622-
profile.BestLevel = level
636+
// 최고 기록 추출 - 마지막 매칭 사용
637+
allBestMatches := profileBestPattern.FindAllStringSubmatch(text, -1)
638+
if len(allBestMatches) > 0 {
639+
matches := allBestMatches[len(allBestMatches)-1]
640+
if len(matches) > 2 {
641+
levelStr := strings.TrimPrefix(matches[1], "+")
642+
if level, err := strconv.Atoi(levelStr); err == nil {
643+
profile.BestLevel = level
644+
}
645+
profile.BestSword = strings.TrimSpace(matches[2])
623646
}
624-
profile.BestSword = strings.TrimSpace(matches[2])
625647
}
626648

627-
// 레벨이 없으면 일반 패턴으로 시도
628-
if profile.Level == -1 {
629-
profile.Level = ExtractLevel(text)
630-
}
649+
// 참고: ExtractLevel fallback 제거 (이전 채팅의 레벨이 잡히는 버그 방지)
631650

632651
return profile
633652
}

0 commit comments

Comments
 (0)