diff --git a/combat/combo.go b/combat/combo.go index c4954d5..110221c 100644 --- a/combat/combo.go +++ b/combat/combo.go @@ -27,7 +27,7 @@ var comboDefs = []ComboDef{ {Class: entity.ClassMage, ActionType: "skill"}, {Class: entity.ClassWarrior, ActionType: "attack"}, }, - Effect: ComboEffect{DamageMultiplier: 1.5, Message: "๐Ÿ’ฅ ICE SHATTER! Frozen enemies shatter!"}, + Effect: ComboEffect{DamageMultiplier: 1.5, Message: "๐Ÿ’ฅ ICE SHATTER! ๋™๊ฒฐ๋œ ์ ์ด ์‚ฐ์‚ฐ์กฐ๊ฐ!"}, }, { Name: "Holy Assault", @@ -35,7 +35,7 @@ var comboDefs = []ComboDef{ {Class: entity.ClassHealer, ActionType: "skill"}, {Class: entity.ClassWarrior, ActionType: "attack"}, }, - Effect: ComboEffect{DamageMultiplier: 1.3, HealAll: 10, Message: "โœจ HOLY ASSAULT! Blessed strikes heal the party!"}, + Effect: ComboEffect{DamageMultiplier: 1.3, HealAll: 10, Message: "โœจ HOLY ASSAULT! ์ถ•๋ณต๋ฐ›์€ ๊ณต๊ฒฉ์ด ํŒŒํ‹ฐ๋ฅผ ์น˜์œ !"}, }, { Name: "Shadow Strike", @@ -43,7 +43,7 @@ var comboDefs = []ComboDef{ {Class: entity.ClassRogue, ActionType: "skill"}, {Class: entity.ClassMage, ActionType: "attack"}, }, - Effect: ComboEffect{DamageMultiplier: 1.4, Message: "๐Ÿ—ก๏ธ SHADOW STRIKE! Magical shadows amplify the attack!"}, + Effect: ComboEffect{DamageMultiplier: 1.4, Message: "๐Ÿ—ก๏ธ SHADOW STRIKE! ๋งˆ๋ฒ•์˜ ๊ทธ๋ฆผ์ž๊ฐ€ ๊ณต๊ฒฉ์„ ์ฆํญ!"}, }, { Name: "Full Assault", @@ -52,7 +52,7 @@ var comboDefs = []ComboDef{ {Class: entity.ClassMage, ActionType: "attack"}, {Class: entity.ClassRogue, ActionType: "attack"}, }, - Effect: ComboEffect{DamageMultiplier: 1.3, BonusDamage: 5, Message: "โš”๏ธ FULL ASSAULT! Combined attack overwhelms!"}, + Effect: ComboEffect{DamageMultiplier: 1.3, BonusDamage: 5, Message: "โš”๏ธ FULL ASSAULT! ํ•ฉ๋™ ๊ณต๊ฒฉ์œผ๋กœ ์••๋„!"}, }, { Name: "Restoration", @@ -60,7 +60,7 @@ var comboDefs = []ComboDef{ {Class: entity.ClassHealer, ActionType: "skill"}, {Class: entity.ClassRogue, ActionType: "item"}, }, - Effect: ComboEffect{HealAll: 20, Message: "๐Ÿ’š RESTORATION! Combined healing surges!"}, + Effect: ComboEffect{HealAll: 20, Message: "๐Ÿ’š RESTORATION! ํ•ฉ๋™ ์น˜์œ ๊ฐ€ ํญ๋ฐœ์ ์œผ๋กœ ๋ฐœ๋™!"}, }, } diff --git a/dungeon/room.go b/dungeon/room.go index b0c7939..69558a4 100644 --- a/dungeon/room.go +++ b/dungeon/room.go @@ -16,7 +16,7 @@ const ( ) func (r RoomType) String() string { - return [...]string{"Combat", "Treasure", "Shop", "Event", "Empty", "Boss", "Secret", "MiniBoss"}[r] + return [...]string{"์ „ํˆฌ", "๋ณด๋ฌผ", "์ƒ์ ", "์ด๋ฒคํŠธ", "๋นˆ ๋ฐฉ", "๋ณด์Šค", "๋น„๋ฐ€", "๋ฏธ๋‹ˆ๋ณด์Šค"}[r] } type Tile int diff --git a/entity/player.go b/entity/player.go index 5f7df6c..587a661 100644 --- a/entity/player.go +++ b/entity/player.go @@ -179,22 +179,22 @@ func (p *Player) TickEffects() []string { if p.HP <= 0 { p.HP = 1 // Poison can't kill, leaves at 1 HP } - msgs = append(msgs, fmt.Sprintf("%s takes %d poison damage", p.Name, e.Value)) + msgs = append(msgs, fmt.Sprintf("%s ๋… ํ”ผํ•ด %d", p.Name, e.Value)) case StatusBurn: p.HP -= e.Value if p.HP <= 0 { p.HP = 0 p.Dead = true } - msgs = append(msgs, fmt.Sprintf("%s takes %d burn damage", p.Name, e.Value)) + msgs = append(msgs, fmt.Sprintf("%s ํ™”์ƒ ํ”ผํ•ด %d", p.Name, e.Value)) case StatusFreeze: - msgs = append(msgs, fmt.Sprintf("%s is frozen!", p.Name)) + msgs = append(msgs, fmt.Sprintf("%s ๋™๊ฒฐ๋จ!", p.Name)) case StatusBleed: p.HP -= e.Value - msgs = append(msgs, fmt.Sprintf("%s takes %d bleed damage", p.Name, e.Value)) + msgs = append(msgs, fmt.Sprintf("%s ์ถœํ˜ˆ ํ”ผํ•ด %d", p.Name, e.Value)) e.Value++ // Bleed intensifies each turn case StatusCurse: - msgs = append(msgs, fmt.Sprintf("%s is cursed! Healing reduced", p.Name)) + msgs = append(msgs, fmt.Sprintf("%s ์ €์ฃผ ์ƒํƒœ! ํšŒ๋ณต๋Ÿ‰ ๊ฐ์†Œ", p.Name)) } if p.HP < 0 { p.HP = 0 diff --git a/entity/player_test.go b/entity/player_test.go index 630addb..3267357 100644 --- a/entity/player_test.go +++ b/entity/player_test.go @@ -200,7 +200,7 @@ func TestBleedEffect(t *testing.T) { p.AddEffect(ActiveEffect{Type: StatusBleed, Duration: 3, Value: 2}) msgs := p.TickEffects() - if len(msgs) == 0 || !strings.Contains(msgs[0], "bleed") { + if len(msgs) == 0 || !strings.Contains(msgs[0], "์ถœํ˜ˆ") { t.Error("expected bleed damage message") } if p.HP != startHP-2 { @@ -231,7 +231,7 @@ func TestFreezeTickMessage(t *testing.T) { p := NewPlayer("Test", ClassMage) p.AddEffect(ActiveEffect{Type: StatusFreeze, Duration: 1, Value: 0}) msgs := p.TickEffects() - if len(msgs) == 0 || !strings.Contains(msgs[0], "frozen") { + if len(msgs) == 0 || !strings.Contains(msgs[0], "๋™๊ฒฐ") { t.Error("expected freeze message") } // Freeze duration 1 -> removed after tick diff --git a/game/emote.go b/game/emote.go index 5535d03..5480493 100644 --- a/game/emote.go +++ b/game/emote.go @@ -1,11 +1,11 @@ package game var emotes = map[string]string{ - "/hi": "๐Ÿ‘‹ waves hello!", - "/gg": "๐ŸŽ‰ says GG!", - "/go": "โš”๏ธ says Let's go!", - "/wait": "โœ‹ says Wait!", - "/help": "๐Ÿ†˜ calls for help!", + "/hi": "๐Ÿ‘‹ ์ธ์‚ฌํ•ฉ๋‹ˆ๋‹ค!", + "/gg": "๐ŸŽ‰ GG!", + "/go": "โš”๏ธ ๊ฐ€์ž!", + "/wait": "โœ‹ ๊ธฐ๋‹ค๋ ค!", + "/help": "๐Ÿ†˜ ๋„์›€ ์š”์ฒญ!", } func ParseEmote(input string) (string, bool) { diff --git a/game/emote_test.go b/game/emote_test.go index bc21243..9c9cc02 100644 --- a/game/emote_test.go +++ b/game/emote_test.go @@ -8,11 +8,11 @@ func TestParseEmote(t *testing.T) { isEmote bool expected string }{ - {"/hi", true, "๐Ÿ‘‹ waves hello!"}, - {"/gg", true, "๐ŸŽ‰ says GG!"}, - {"/go", true, "โš”๏ธ says Let's go!"}, - {"/wait", true, "โœ‹ says Wait!"}, - {"/help", true, "๐Ÿ†˜ calls for help!"}, + {"/hi", true, "๐Ÿ‘‹ ์ธ์‚ฌํ•ฉ๋‹ˆ๋‹ค!"}, + {"/gg", true, "๐ŸŽ‰ GG!"}, + {"/go", true, "โš”๏ธ ๊ฐ€์ž!"}, + {"/wait", true, "โœ‹ ๊ธฐ๋‹ค๋ ค!"}, + {"/help", true, "๐Ÿ†˜ ๋„์›€ ์š”์ฒญ!"}, {"/unknown", false, ""}, {"hello", false, ""}, {"", false, ""}, diff --git a/game/event.go b/game/event.go index 604024d..6db7cf6 100644 --- a/game/event.go +++ b/game/event.go @@ -41,7 +41,7 @@ func (s *GameSession) EnterRoom(roomIdx int) { s.signalCombat() case dungeon.RoomShop: if s.hasMutation("no_shop") { - s.addLog("The shop is closed! (Weekly mutation)") + s.addLog("์ƒ์ ์ด ๋‹ซํ˜”์Šต๋‹ˆ๋‹ค! (์ฃผ๊ฐ„ ๋ณ€์ด)") room.Cleared = true return } @@ -169,7 +169,7 @@ func (s *GameSession) grantTreasure() { floor := s.state.FloorNum for _, p := range s.state.Players { if len(p.Inventory) >= s.cfg.Game.InventoryLimit { - s.addLog(fmt.Sprintf("%s's inventory is full!", p.Name)) + s.addLog(fmt.Sprintf("%s์˜ ์ธ๋ฒคํ† ๋ฆฌ๊ฐ€ ๊ฐ€๋“ ์ฐผ์Šต๋‹ˆ๋‹ค!", p.Name)) continue } if rand.Float64() < 0.5 { @@ -178,14 +178,14 @@ func (s *GameSession) grantTreasure() { Name: weaponName(floor), Type: entity.ItemWeapon, Bonus: bonus, } p.Inventory = append(p.Inventory, item) - s.addLog(fmt.Sprintf("%s found %s (ATK+%d)", p.Name, item.Name, item.Bonus)) + s.addLog(fmt.Sprintf("%s %s ๋ฐœ๊ฒฌ (ATK+%d)", p.Name, item.Name, item.Bonus)) } else { bonus := 2 + rand.Intn(4) + floor/4 item := entity.Item{ Name: armorName(floor), Type: entity.ItemArmor, Bonus: bonus, } p.Inventory = append(p.Inventory, item) - s.addLog(fmt.Sprintf("%s found %s (DEF+%d)", p.Name, item.Name, item.Bonus)) + s.addLog(fmt.Sprintf("%s %s ๋ฐœ๊ฒฌ (DEF+%d)", p.Name, item.Name, item.Bonus)) } } } @@ -245,7 +245,7 @@ func armorName(floor int) string { func (s *GameSession) triggerEvent() { event := PickRandomEvent() s.state.LastEventName = event.Name - s.addLog(fmt.Sprintf("Event: %s โ€” %s", event.Name, event.Description)) + s.addLog(fmt.Sprintf("์ด๋ฒคํŠธ: %s โ€” %s", event.Name, event.Description)) // Auto-resolve with a random choice choice := event.Choices[rand.Intn(len(event.Choices))] @@ -267,10 +267,10 @@ func (s *GameSession) triggerEvent() { if outcome.HPChange > 0 { before := target.HP target.Heal(outcome.HPChange) - s.addLog(fmt.Sprintf(" %s heals %d HP", target.Name, target.HP-before)) + s.addLog(fmt.Sprintf(" %s HP %d ํšŒ๋ณต", target.Name, target.HP-before)) } else if outcome.HPChange < 0 { target.TakeDamage(-outcome.HPChange) - s.addLog(fmt.Sprintf(" %s takes %d damage", target.Name, -outcome.HPChange)) + s.addLog(fmt.Sprintf(" %s %d ํ”ผํ•ด๋ฅผ ๋ฐ›์Œ", target.Name, -outcome.HPChange)) } if outcome.GoldChange != 0 { @@ -279,9 +279,9 @@ func (s *GameSession) triggerEvent() { target.Gold = 0 } if outcome.GoldChange > 0 { - s.addLog(fmt.Sprintf(" %s gains %d gold", target.Name, outcome.GoldChange)) + s.addLog(fmt.Sprintf(" %s ๊ณจ๋“œ %d ํš๋“", target.Name, outcome.GoldChange)) } else { - s.addLog(fmt.Sprintf(" %s loses %d gold", target.Name, -outcome.GoldChange)) + s.addLog(fmt.Sprintf(" %s ๊ณจ๋“œ %d ์žƒ์Œ", target.Name, -outcome.GoldChange)) } } @@ -292,27 +292,27 @@ func (s *GameSession) triggerEvent() { bonus := 3 + rand.Intn(6) + floor/3 item := entity.Item{Name: weaponName(floor), Type: entity.ItemWeapon, Bonus: bonus} target.Inventory = append(target.Inventory, item) - s.addLog(fmt.Sprintf(" %s found %s (ATK+%d)", target.Name, item.Name, item.Bonus)) + s.addLog(fmt.Sprintf(" %s %s ๋ฐœ๊ฒฌ (ATK+%d)", target.Name, item.Name, item.Bonus)) } else { bonus := 2 + rand.Intn(4) + floor/4 item := entity.Item{Name: armorName(floor), Type: entity.ItemArmor, Bonus: bonus} target.Inventory = append(target.Inventory, item) - s.addLog(fmt.Sprintf(" %s found %s (DEF+%d)", target.Name, item.Name, item.Bonus)) + s.addLog(fmt.Sprintf(" %s %s ๋ฐœ๊ฒฌ (DEF+%d)", target.Name, item.Name, item.Bonus)) } } else { - s.addLog(fmt.Sprintf(" %s's inventory is full!", target.Name)) + s.addLog(fmt.Sprintf(" %s์˜ ์ธ๋ฒคํ† ๋ฆฌ๊ฐ€ ๊ฐ€๋“ ์ฐผ์Šต๋‹ˆ๋‹ค!", target.Name)) } } } func (s *GameSession) grantSecretTreasure() { - s.addLog("You discovered a secret room filled with treasure!") + s.addLog("๋ณด๋ฌผ๋กœ ๊ฐ€๋“ ์ฐฌ ๋น„๋ฐ€์˜ ๋ฐฉ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค!") floor := s.state.FloorNum // Double treasure: grant two items per player for _, p := range s.state.Players { for i := 0; i < 2; i++ { if len(p.Inventory) >= s.cfg.Game.InventoryLimit { - s.addLog(fmt.Sprintf("%s's inventory is full!", p.Name)) + s.addLog(fmt.Sprintf("%s์˜ ์ธ๋ฒคํ† ๋ฆฌ๊ฐ€ ๊ฐ€๋“ ์ฐผ์Šต๋‹ˆ๋‹ค!", p.Name)) break } if rand.Float64() < 0.5 { @@ -321,14 +321,14 @@ func (s *GameSession) grantSecretTreasure() { Name: weaponName(floor), Type: entity.ItemWeapon, Bonus: bonus, } p.Inventory = append(p.Inventory, item) - s.addLog(fmt.Sprintf("%s found %s (ATK+%d)", p.Name, item.Name, item.Bonus)) + s.addLog(fmt.Sprintf("%s %s ๋ฐœ๊ฒฌ (ATK+%d)", p.Name, item.Name, item.Bonus)) } else { bonus := 2 + rand.Intn(4) + floor/4 item := entity.Item{ Name: armorName(floor), Type: entity.ItemArmor, Bonus: bonus, } p.Inventory = append(p.Inventory, item) - s.addLog(fmt.Sprintf("%s found %s (DEF+%d)", p.Name, item.Name, item.Bonus)) + s.addLog(fmt.Sprintf("%s %s ๋ฐœ๊ฒฌ (DEF+%d)", p.Name, item.Name, item.Bonus)) } } } @@ -376,7 +376,7 @@ func (s *GameSession) spawnMiniBoss() { miniBoss.ATK = int(float64(miniBoss.ATK) * mult) } s.state.Monsters = []*entity.Monster{miniBoss} - s.addLog(fmt.Sprintf("A mini-boss appears: %s!", miniBoss.Name)) + s.addLog(fmt.Sprintf("๋ฏธ๋‹ˆ๋ณด์Šค ๋“ฑ์žฅ: %s!", miniBoss.Name)) // Reset skill uses for all players at combat start for _, p := range s.state.Players { diff --git a/game/lobby.go b/game/lobby.go index f5ab6e3..50a09ae 100644 --- a/game/lobby.go +++ b/game/lobby.go @@ -117,10 +117,10 @@ func (l *Lobby) InvitePlayer(roomCode, fingerprint string) error { defer l.mu.Unlock() p, ok := l.online[fingerprint] if !ok { - return fmt.Errorf("player not online") + return fmt.Errorf("ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์˜จ๋ผ์ธ์ด ์•„๋‹™๋‹ˆ๋‹ค") } if p.InRoom != "" { - return fmt.Errorf("player already in a room") + return fmt.Errorf("ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ด๋ฏธ ๋ฐฉ์— ์žˆ์Šต๋‹ˆ๋‹ค") } // Store the invite as a pending field p.InRoom = "invited:" + roomCode @@ -148,13 +148,13 @@ func (l *Lobby) JoinRoom(code, playerName, fingerprint string) error { defer l.mu.Unlock() room, ok := l.rooms[code] if !ok { - return fmt.Errorf("room %s not found", code) + return fmt.Errorf("๋ฐฉ %s์„(๋ฅผ) ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค", code) } if len(room.Players) >= l.cfg.Game.MaxPlayers { - return fmt.Errorf("room %s is full", code) + return fmt.Errorf("๋ฐฉ %s์ด(๊ฐ€) ๊ฐ€๋“ ์ฐผ์Šต๋‹ˆ๋‹ค", code) } if room.Status != RoomWaiting { - return fmt.Errorf("room %s already in progress", code) + return fmt.Errorf("๋ฐฉ %s์ด(๊ฐ€) ์ด๋ฏธ ์ง„ํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค", code) } room.Players = append(room.Players, LobbyPlayer{Name: playerName, Fingerprint: fingerprint}) slog.Info("player joined", "room", code, "player", playerName) diff --git a/game/mutation.go b/game/mutation.go index 94098cf..aa33650 100644 --- a/game/mutation.go +++ b/game/mutation.go @@ -19,15 +19,15 @@ type Mutation struct { // Mutations is the list of all available mutations. var Mutations = []Mutation{ - {ID: "no_skills", Name: "Skill Lockout", Description: "Class skills are disabled", + {ID: "no_skills", Name: "์Šคํ‚ฌ ๋ด‰์ธ", Description: "์ง์—… ์Šคํ‚ฌ ์‚ฌ์šฉ ๋ถˆ๊ฐ€", Apply: func(cfg *config.GameConfig) { cfg.SkillUses = 0 }}, - {ID: "speed_run", Name: "Speed Run", Description: "Turn timeout halved", + {ID: "speed_run", Name: "์Šคํ”ผ๋“œ ๋Ÿฐ", Description: "ํ„ด ์ œํ•œ ์‹œ๊ฐ„ ์ ˆ๋ฐ˜", Apply: func(cfg *config.GameConfig) { cfg.TurnTimeoutSec = max(cfg.TurnTimeoutSec/2, 2) }}, - {ID: "no_shop", Name: "Shop Closed", Description: "Shops are unavailable", + {ID: "no_shop", Name: "์ƒ์  ํ์‡„", Description: "์ƒ์  ์ด์šฉ ๋ถˆ๊ฐ€", Apply: func(cfg *config.GameConfig) {}}, // handled at runtime in EnterRoom - {ID: "glass_cannon", Name: "Glass Cannon", Description: "Double damage, half HP", + {ID: "glass_cannon", Name: "์œ ๋ฆฌ ๋Œ€ํฌ", Description: "ํ”ผํ•ด 2๋ฐฐ, HP ์ ˆ๋ฐ˜", Apply: func(cfg *config.GameConfig) {}}, // handled at runtime in AddPlayer/spawnMonsters - {ID: "elite_flood", Name: "Elite Flood", Description: "All monsters are elite", + {ID: "elite_flood", Name: "์—˜๋ฆฌํŠธ ๋ฒ”๋žŒ", Description: "๋ชจ๋“  ๋ชฌ์Šคํ„ฐ๊ฐ€ ์—˜๋ฆฌํŠธ", Apply: func(cfg *config.GameConfig) {}}, // handled at runtime in spawnMonsters } diff --git a/game/random_event.go b/game/random_event.go index 0c1083e..a58ec86 100644 --- a/game/random_event.go +++ b/game/random_event.go @@ -28,211 +28,211 @@ func GetRandomEvents() []RandomEvent { return []RandomEvent{ { Name: "altar", - Description: "You discover an ancient altar glowing with strange energy.", + Description: "์ด์ƒํ•œ ์—๋„ˆ์ง€๋กœ ๋น›๋‚˜๋Š” ๊ณ ๋Œ€ ์ œ๋‹จ์„ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค.", Choices: []EventChoice{ { - Label: "Pray at the altar", + Label: "์ œ๋‹จ์—์„œ ๊ธฐ๋„ํ•˜๊ธฐ", Resolve: func(floor int) EventOutcome { if rand.Float64() < 0.6 { heal := 15 + floor*2 - return EventOutcome{HPChange: heal, Description: "The altar blesses you with healing light."} + return EventOutcome{HPChange: heal, Description: "์ œ๋‹จ์ด ์น˜์œ ์˜ ๋น›์œผ๋กœ ์ถ•๋ณตํ•ฉ๋‹ˆ๋‹ค."} } dmg := 10 + floor - return EventOutcome{HPChange: -dmg, Description: "The altar's energy lashes out at you!"} + return EventOutcome{HPChange: -dmg, Description: "์ œ๋‹จ์˜ ์—๋„ˆ์ง€๊ฐ€ ๋‹น์‹ ์„ ๊ณต๊ฒฉํ•ฉ๋‹ˆ๋‹ค!"} }, }, { - Label: "Offer gold", + Label: "๊ณจ๋“œ ๋ฐ”์น˜๊ธฐ", Resolve: func(floor int) EventOutcome { cost := 10 + floor - return EventOutcome{GoldChange: -cost, ItemDrop: true, Description: "You offer gold and receive a divine gift."} + return EventOutcome{GoldChange: -cost, ItemDrop: true, Description: "๊ณจ๋“œ๋ฅผ ๋ฐ”์น˜๊ณ  ์‹ ์„ฑํ•œ ์„ ๋ฌผ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค."} }, }, { - Label: "Walk away", + Label: "๊ทธ๋ƒฅ ์ง€๋‚˜๊ฐ€๊ธฐ", Resolve: func(floor int) EventOutcome { - return EventOutcome{Description: "You leave the altar undisturbed."} + return EventOutcome{Description: "์ œ๋‹จ์„ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๊ณ  ๋– ๋‚ฉ๋‹ˆ๋‹ค."} }, }, }, }, { Name: "fountain", - Description: "A shimmering fountain bubbles in the center of the room.", + Description: "๋ฐฉ ์ค‘์•™์—์„œ ๋น›๋‚˜๋Š” ๋ถ„์ˆ˜๊ฐ€ ์†Ÿ์•„์˜ค๋ฆ…๋‹ˆ๋‹ค.", Choices: []EventChoice{ { - Label: "Drink from the fountain", + Label: "๋ถ„์ˆ˜์˜ ๋ฌผ ๋งˆ์‹œ๊ธฐ", Resolve: func(floor int) EventOutcome { heal := 20 + floor*2 - return EventOutcome{HPChange: heal, Description: "The water rejuvenates you!"} + return EventOutcome{HPChange: heal, Description: "๋ฌผ์ด ๋‹น์‹ ์„ ํ™œ๊ธฐ์ฐจ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค!"} }, }, { - Label: "Toss a coin", + Label: "๋™์ „ ๋˜์ง€๊ธฐ", Resolve: func(floor int) EventOutcome { if rand.Float64() < 0.5 { gold := 15 + floor*3 - return EventOutcome{GoldChange: gold, Description: "The fountain rewards your generosity!"} + return EventOutcome{GoldChange: gold, Description: "๋ถ„์ˆ˜๊ฐ€ ๋‹น์‹ ์˜ ๊ด€๋Œ€ํ•จ์— ๋ณด๋‹ตํ•ฉ๋‹ˆ๋‹ค!"} } - return EventOutcome{GoldChange: -5, Description: "The coin sinks and nothing happens."} + return EventOutcome{GoldChange: -5, Description: "๋™์ „์ด ๊ฐ€๋ผ์•‰๊ณ  ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."} }, }, }, }, { Name: "merchant", - Description: "A hooded merchant appears from the shadows.", + Description: "๋‘๊ฑด์„ ์“ด ์ƒ์ธ์ด ์–ด๋‘  ์†์—์„œ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.", Choices: []EventChoice{ { - Label: "Trade gold for healing", + Label: "๊ณจ๋“œ๋กœ ์น˜๋ฃŒ ๊ฑฐ๋ž˜", Resolve: func(floor int) EventOutcome { cost := 15 + floor heal := 25 + floor*2 - return EventOutcome{HPChange: heal, GoldChange: -cost, Description: "The merchant sells you a healing draught."} + return EventOutcome{HPChange: heal, GoldChange: -cost, Description: "์ƒ์ธ์ด ์น˜์œ ์˜ ๋ฌผ์•ฝ์„ ํŒ๋‹ˆ๋‹ค."} }, }, { - Label: "Buy a mystery item", + Label: "๋ฏธ์Šคํ„ฐ๋ฆฌ ์•„์ดํ…œ ๊ตฌ๋งค", Resolve: func(floor int) EventOutcome { cost := 20 + floor*2 - return EventOutcome{GoldChange: -cost, ItemDrop: true, Description: "The merchant hands you a wrapped package."} + return EventOutcome{GoldChange: -cost, ItemDrop: true, Description: "์ƒ์ธ์ด ํฌ์žฅ๋œ ๊พธ๋Ÿฌ๋ฏธ๋ฅผ ๊ฑด๋„ต๋‹ˆ๋‹ค."} }, }, { - Label: "Decline", + Label: "๊ฑฐ์ ˆํ•˜๊ธฐ", Resolve: func(floor int) EventOutcome { - return EventOutcome{Description: "The merchant vanishes into the shadows."} + return EventOutcome{Description: "์ƒ์ธ์ด ์–ด๋‘  ์†์œผ๋กœ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค."} }, }, }, }, { Name: "trap_room", - Description: "The floor is covered with suspicious pressure plates.", + Description: "๋ฐ”๋‹ฅ์ด ์ˆ˜์ƒํ•œ ์••๋ ฅํŒ์œผ๋กœ ๋ฎ์—ฌ ์žˆ์Šต๋‹ˆ๋‹ค.", Choices: []EventChoice{ { - Label: "Carefully navigate", + Label: "์กฐ์‹ฌํžˆ ์ง€๋‚˜๊ฐ€๊ธฐ", Resolve: func(floor int) EventOutcome { if rand.Float64() < 0.5 { - return EventOutcome{Description: "You skillfully avoid all the traps!"} + return EventOutcome{Description: "๋Šฅ์ˆ™ํ•˜๊ฒŒ ๋ชจ๋“  ํ•จ์ •์„ ํ”ผํ–ˆ์Šต๋‹ˆ๋‹ค!"} } dmg := 8 + floor - return EventOutcome{HPChange: -dmg, Description: "You trigger a trap and take damage!"} + return EventOutcome{HPChange: -dmg, Description: "ํ•จ์ •์„ ๋ฐŸ์•„ ํ”ผํ•ด๋ฅผ ์ž…์—ˆ์Šต๋‹ˆ๋‹ค!"} }, }, { - Label: "Rush through", + Label: "๋Œ์ง„ํ•˜๊ธฐ", Resolve: func(floor int) EventOutcome { dmg := 5 + floor/2 gold := 10 + floor*2 - return EventOutcome{HPChange: -dmg, GoldChange: gold, Description: "You take minor damage but find hidden gold!"} + return EventOutcome{HPChange: -dmg, GoldChange: gold, Description: "์•ฝ๊ฐ„์˜ ํ”ผํ•ด๋ฅผ ์ž…์—ˆ์ง€๋งŒ ์ˆจ๊ฒจ์ง„ ๊ณจ๋“œ๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค!"} }, }, }, }, { Name: "shrine", - Description: "A glowing shrine hums with divine power.", + Description: "์‹ ์„ฑํ•œ ํž˜์œผ๋กœ ์šธ๋ฆฌ๋Š” ๋น›๋‚˜๋Š” ์„ฑ์†Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.", Choices: []EventChoice{ { - Label: "Kneel and pray", + Label: "๋ฌด๋ฆŽ ๊ฟ‡๊ณ  ๊ธฐ๋„ํ•˜๊ธฐ", Resolve: func(floor int) EventOutcome { heal := 30 + floor*2 - return EventOutcome{HPChange: heal, Description: "The shrine fills you with renewed vigor!"} + return EventOutcome{HPChange: heal, Description: "์„ฑ์†Œ๊ฐ€ ์ƒˆ๋กœ์šด ํ™œ๋ ฅ์œผ๋กœ ๊ฐ€๋“ ์ฑ„์›Œ์ค๋‹ˆ๋‹ค!"} }, }, { - Label: "Take the offering", + Label: "์ œ๋ฌผ ๊ฐ€์ ธ๊ฐ€๊ธฐ", Resolve: func(floor int) EventOutcome { gold := 20 + floor*3 dmg := 15 + floor - return EventOutcome{HPChange: -dmg, GoldChange: gold, Description: "You steal the offering but anger the spirits!"} + return EventOutcome{HPChange: -dmg, GoldChange: gold, Description: "์ œ๋ฌผ์„ ํ›”์ณค์ง€๋งŒ ์˜ํ˜ผ๋“ค์ด ๋ถ„๋…ธํ•ฉ๋‹ˆ๋‹ค!"} }, }, }, }, { Name: "chest", - Description: "An ornate chest sits in the corner of the room.", + Description: "๋ฐฉ ๊ตฌ์„์— ํ™”๋ คํ•œ ์ƒ์ž๊ฐ€ ๋†“์—ฌ ์žˆ์Šต๋‹ˆ๋‹ค.", Choices: []EventChoice{ { - Label: "Open carefully", + Label: "์กฐ์‹ฌํžˆ ์—ด๊ธฐ", Resolve: func(floor int) EventOutcome { if rand.Float64() < 0.7 { gold := 15 + floor*2 - return EventOutcome{GoldChange: gold, Description: "The chest contains a pile of gold!"} + return EventOutcome{GoldChange: gold, Description: "์ƒ์ž ์•ˆ์— ๊ณจ๋“œ ๋”๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค!"} } dmg := 12 + floor - return EventOutcome{HPChange: -dmg, Description: "The chest was a mimic! It bites you!"} + return EventOutcome{HPChange: -dmg, Description: "์ƒ์ž๊ฐ€ ๋ฏธ๋ฏน์ด์—ˆ์Šต๋‹ˆ๋‹ค! ๋ฌผ์–ด๋œฏ๊น๋‹ˆ๋‹ค!"} }, }, { - Label: "Smash it open", + Label: "๋ถ€์ˆ˜์–ด ์—ด๊ธฐ", Resolve: func(floor int) EventOutcome { - return EventOutcome{ItemDrop: true, Description: "You smash the chest and find equipment inside!"} + return EventOutcome{ItemDrop: true, Description: "์ƒ์ž๋ฅผ ๋ถ€์ˆ˜๊ณ  ์•ˆ์—์„œ ์žฅ๋น„๋ฅผ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค!"} }, }, { - Label: "Leave it", + Label: "๊ทธ๋ƒฅ ๋‘๊ธฐ", Resolve: func(floor int) EventOutcome { - return EventOutcome{Description: "Better safe than sorry."} + return EventOutcome{Description: "์•ˆ์ „ํ•œ ๊ฒŒ ์ตœ๊ณ ์ž…๋‹ˆ๋‹ค."} }, }, }, }, { Name: "ghost", - Description: "A spectral figure materializes before you.", + Description: "์œ ๋ น ๊ฐ™์€ ํ˜•์ฒด๊ฐ€ ๋ˆˆ์•ž์— ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.", Choices: []EventChoice{ { - Label: "Speak with the ghost", + Label: "์œ ๋ น๊ณผ ๋Œ€ํ™”ํ•˜๊ธฐ", Resolve: func(floor int) EventOutcome { gold := 10 + floor*2 - return EventOutcome{GoldChange: gold, Description: "The ghost thanks you for listening and rewards you."} + return EventOutcome{GoldChange: gold, Description: "์œ ๋ น์ด ๋“ค์–ด์ค˜์„œ ๊ฐ์‚ฌํ•˜๋ฉฐ ๋ณด์ƒํ•ฉ๋‹ˆ๋‹ค."} }, }, { - Label: "Attack the ghost", + Label: "์œ ๋ น ๊ณต๊ฒฉํ•˜๊ธฐ", Resolve: func(floor int) EventOutcome { if rand.Float64() < 0.4 { - return EventOutcome{ItemDrop: true, Description: "The ghost drops a spectral weapon as it fades!"} + return EventOutcome{ItemDrop: true, Description: "์œ ๋ น์ด ์‚ฌ๋ผ์ง€๋ฉฐ ์œ ๋ น ๋ฌด๊ธฐ๋ฅผ ๋–จ์–ด๋œจ๋ฆฝ๋‹ˆ๋‹ค!"} } dmg := 15 + floor - return EventOutcome{HPChange: -dmg, Description: "The ghost retaliates with ghostly fury!"} + return EventOutcome{HPChange: -dmg, Description: "์œ ๋ น์ด ๋ถ„๋…ธํ•˜์—ฌ ๋ฐ˜๊ฒฉํ•ฉ๋‹ˆ๋‹ค!"} }, }, }, }, { Name: "mushroom", - Description: "Strange glowing mushrooms grow in clusters here.", + Description: "์ด์ƒํ•˜๊ฒŒ ๋น›๋‚˜๋Š” ๋ฒ„์„ฏ๋“ค์ด ๋ฌด๋ฆฌ ์ง€์–ด ์ž๋ผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.", Choices: []EventChoice{ { - Label: "Eat a mushroom", + Label: "๋ฒ„์„ฏ ๋จน๊ธฐ", Resolve: func(floor int) EventOutcome { r := rand.Float64() if r < 0.33 { heal := 20 + floor*2 - return EventOutcome{HPChange: heal, Description: "The mushroom tastes great and heals you!"} + return EventOutcome{HPChange: heal, Description: "๋ฒ„์„ฏ์ด ๋ง›์žˆ๊ณ  ์น˜์œ  ํšจ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค!"} } else if r < 0.66 { dmg := 10 + floor - return EventOutcome{HPChange: -dmg, Description: "The mushroom was poisonous!"} + return EventOutcome{HPChange: -dmg, Description: "๋…๋ฒ„์„ฏ์ด์—ˆ์Šต๋‹ˆ๋‹ค!"} } gold := 10 + floor - return EventOutcome{GoldChange: gold, Description: "The mushroom gives you strange visions... and gold falls from above!"} + return EventOutcome{GoldChange: gold, Description: "๋ฒ„์„ฏ์ด ์ด์ƒํ•œ ํ™˜๊ฐ์„ ๋ณด์—ฌ์ฃผ๊ณ ... ์œ„์—์„œ ๊ณจ๋“œ๊ฐ€ ๋–จ์–ด์ง‘๋‹ˆ๋‹ค!"} }, }, { - Label: "Collect and sell", + Label: "์ฑ„์ง‘ํ•˜์—ฌ ํŒ”๊ธฐ", Resolve: func(floor int) EventOutcome { gold := 8 + floor - return EventOutcome{GoldChange: gold, Description: "You carefully harvest the mushrooms for sale."} + return EventOutcome{GoldChange: gold, Description: "์กฐ์‹ฌํžˆ ๋ฒ„์„ฏ์„ ์ฑ„์ง‘ํ•˜์—ฌ ํŒ๋งคํ•ฉ๋‹ˆ๋‹ค."} }, }, { - Label: "Ignore them", + Label: "๋ฌด์‹œํ•˜๊ธฐ", Resolve: func(floor int) EventOutcome { - return EventOutcome{Description: "You wisely avoid the mysterious fungi."} + return EventOutcome{Description: "์˜๋ฌธ์˜ ๊ท ๋ฅ˜๋ฅผ ํ˜„๋ช…ํ•˜๊ฒŒ ํ”ผํ•ฉ๋‹ˆ๋‹ค."} }, }, }, diff --git a/game/session.go b/game/session.go index e891129..9d9eea9 100644 --- a/game/session.go +++ b/game/session.go @@ -176,7 +176,7 @@ func (s *GameSession) combatLoop() { if last, ok := s.lastActivity[p.Fingerprint]; ok { if now.Sub(last) > 60*time.Second { slog.Warn("player inactive removed", "fingerprint", p.Fingerprint, "name", p.Name) - s.addLog(fmt.Sprintf("%s removed (disconnected)", p.Name)) + s.addLog(fmt.Sprintf("%s ์ œ๊ฑฐ๋จ (์ ‘์† ๋Š๊น€)", p.Name)) changed = true continue } @@ -335,15 +335,15 @@ func (s *GameSession) SubmitAction(playerID string, action PlayerAction) { desc := "" switch action.Type { case ActionAttack: - desc = "Attacking" + desc = "๊ณต๊ฒฉ" case ActionSkill: - desc = "Using Skill" + desc = "์Šคํ‚ฌ ์‚ฌ์šฉ" case ActionItem: - desc = "Using Item" + desc = "์•„์ดํ…œ ์‚ฌ์šฉ" case ActionFlee: - desc = "Fleeing" + desc = "๋„์ฃผ" case ActionWait: - desc = "Defending" + desc = "๋ฐฉ์–ด" } if s.state.SubmittedActions == nil { s.state.SubmittedActions = make(map[string]string) @@ -382,12 +382,12 @@ func (s *GameSession) AllocateSkillPoint(fingerprint string, branchIdx int) erro for _, p := range s.state.Players { if p.Fingerprint == fingerprint { if p.Skills == nil || p.Skills.Points <= p.Skills.Allocated { - return fmt.Errorf("no skill points available") + return fmt.Errorf("์Šคํ‚ฌ ํฌ์ธํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค") } return p.Skills.Allocate(branchIdx, p.Class) } } - return fmt.Errorf("player not found") + return fmt.Errorf("ํ”Œ๋ ˆ์ด์–ด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค") } // BuyResult describes the outcome of a shop purchase attempt. diff --git a/game/turn.go b/game/turn.go index 21747f8..f91422a 100644 --- a/game/turn.go +++ b/game/turn.go @@ -99,13 +99,13 @@ func (s *GameSession) resolvePlayerActions() { bonus := int(float64(e.Value) * (theme.DamageMult - 1.0)) if bonus > 0 { p.TakeDamage(bonus) - s.addLog(fmt.Sprintf(" (%s theme: +%d damage)", theme.Name, bonus)) + s.addLog(fmt.Sprintf(" (%s ํ…Œ๋งˆ: +%d ํ”ผํ•ด)", theme.Name, bonus)) } } } if p.IsDead() { - s.addLog(fmt.Sprintf("โ˜  %s has fallen!", p.Name)) + s.addLog(fmt.Sprintf("โ˜  %s ์“ฐ๋Ÿฌ์กŒ์Šต๋‹ˆ๋‹ค!", p.Name)) } } } @@ -127,7 +127,7 @@ func (s *GameSession) resolvePlayerActions() { } // Frozen players skip their action if frozenPlayers[p.Fingerprint] { - s.addLog(fmt.Sprintf("%s is frozen and cannot act!", p.Name)) + s.addLog(fmt.Sprintf("%s ๋™๊ฒฐ๋˜์–ด ํ–‰๋™ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค!", p.Name)) continue } action, ok := s.actions[p.Fingerprint] @@ -146,7 +146,7 @@ func (s *GameSession) resolvePlayerActions() { intentOwners = append(intentOwners, p.Name) case ActionSkill: if p.SkillUses <= 0 { - s.addLog(fmt.Sprintf("%s has no skill uses left!", p.Name)) + s.addLog(fmt.Sprintf("%s ์Šคํ‚ฌ ์‚ฌ์šฉ ํšŸ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค!", p.Name)) break } p.SkillUses-- @@ -158,7 +158,7 @@ func (s *GameSession) resolvePlayerActions() { m.TauntTurns = 2 } } - s.addLog(fmt.Sprintf("%s used Taunt! Enemies focus on %s for 2 turns", p.Name, p.Name)) + s.addLog(fmt.Sprintf("%s Taunt ์‚ฌ์šฉ! ์ ๋“ค์ด 2ํ„ด๊ฐ„ %s๋ฅผ ์ง‘์ค‘ ๊ณต๊ฒฉํ•ฉ๋‹ˆ๋‹ค", p.Name, p.Name)) case entity.ClassMage: skillPower := 0 if p.Skills != nil { @@ -197,13 +197,13 @@ func (s *GameSession) resolvePlayerActions() { } before := target.HP target.Heal(healAmount) - s.addLog(fmt.Sprintf("%s healed %s for %d HP", p.Name, target.Name, target.HP-before)) + s.addLog(fmt.Sprintf("%s์ด(๊ฐ€) %s์—๊ฒŒ HP %d ํšŒ๋ณต", p.Name, target.Name, target.HP-before)) case entity.ClassRogue: currentRoom := s.state.Floor.Rooms[s.state.Floor.CurrentRoom] for _, neighborIdx := range currentRoom.Neighbors { s.state.Floor.Rooms[neighborIdx].Visited = true } - s.addLog(fmt.Sprintf("%s scouted nearby rooms!", p.Name)) + s.addLog(fmt.Sprintf("%s ์ฃผ๋ณ€ ๋ฐฉ์„ ์ •์ฐฐํ–ˆ์Šต๋‹ˆ๋‹ค!", p.Name)) } case ActionItem: found := false @@ -216,17 +216,17 @@ func (s *GameSession) resolvePlayerActions() { } p.Heal(healAmt) p.Inventory = append(p.Inventory[:i], p.Inventory[i+1:]...) - s.addLog(fmt.Sprintf("%s used %s, restored %d HP", p.Name, item.Name, p.HP-before)) + s.addLog(fmt.Sprintf("%s %s ์‚ฌ์šฉ, HP %d ํšŒ๋ณต", p.Name, item.Name, p.HP-before)) found = true break } } if !found { - s.addLog(fmt.Sprintf("%s has no items to use!", p.Name)) + s.addLog(fmt.Sprintf("%s ์‚ฌ์šฉํ•  ์•„์ดํ…œ์ด ์—†์Šต๋‹ˆ๋‹ค!", p.Name)) } case ActionFlee: if combat.AttemptFlee(s.cfg.Combat.FleeChance) { - s.addLog(fmt.Sprintf("%s fled from battle!", p.Name)) + s.addLog(fmt.Sprintf("%s ์ „ํˆฌ์—์„œ ๋„์ฃผํ–ˆ์Šต๋‹ˆ๋‹ค!", p.Name)) s.state.FleeSucceeded = true if s.state.SoloMode { s.state.Phase = PhaseExploring @@ -234,10 +234,10 @@ func (s *GameSession) resolvePlayerActions() { } p.Fled = true } else { - s.addLog(fmt.Sprintf("%s failed to flee!", p.Name)) + s.addLog(fmt.Sprintf("%s ๋„์ฃผ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค!", p.Name)) } case ActionWait: - s.addLog(fmt.Sprintf("%s is defending", p.Name)) + s.addLog(fmt.Sprintf("%s ๋ฐฉ์–ด ์ค‘", p.Name)) } } @@ -252,7 +252,7 @@ func (s *GameSession) resolvePlayerActions() { if allFled && !s.state.SoloMode { s.state.Phase = PhaseExploring s.state.Floor.Rooms[s.state.Floor.CurrentRoom].Cleared = true - s.addLog("All players fled!") + s.addLog("๋ชจ๋“  ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๋„์ฃผํ–ˆ์Šต๋‹ˆ๋‹ค!") for _, p := range s.state.Players { p.Fled = false } @@ -307,16 +307,16 @@ func (s *GameSession) resolvePlayerActions() { if r.IsAoE { coopStr := "" if r.CoopApplied { - coopStr = " (co-op!)" + coopStr = " (ํ˜‘๋™!)" } - s.addLog(fmt.Sprintf("%s hit all enemies for %d total dmg%s", owner, r.Damage, coopStr)) + s.addLog(fmt.Sprintf("%s ์ „์ฒด ์ ์—๊ฒŒ ์ด %d ํ”ผํ•ด%s", owner, r.Damage, coopStr)) } else if r.TargetIdx >= 0 && r.TargetIdx < len(s.state.Monsters) { target := s.state.Monsters[r.TargetIdx] coopStr := "" if r.CoopApplied { - coopStr = " (co-op!)" + coopStr = " (ํ˜‘๋™!)" } - s.addLog(fmt.Sprintf("%s hit %s for %d dmg%s", owner, target.Name, r.Damage, coopStr)) + s.addLog(fmt.Sprintf("%s์ด(๊ฐ€) %s์—๊ฒŒ %d ํ”ผํ•ด%s", owner, target.Name, r.Damage, coopStr)) } // Apply Life Siphon relic: heal percentage of damage dealt if r.Damage > 0 { @@ -326,7 +326,7 @@ func (s *GameSession) resolvePlayerActions() { heal := r.Damage * rel.Value / 100 if heal > 0 { p.Heal(heal) - s.addLog(fmt.Sprintf(" %s's Life Siphon heals %d HP", p.Name, heal)) + s.addLog(fmt.Sprintf(" %s์˜ Life Siphon์œผ๋กœ HP %d ํšŒ๋ณต", p.Name, heal)) } } } @@ -359,13 +359,13 @@ func (s *GameSession) resolvePlayerActions() { } if r.Effect == entity.RelicHealOnKill { p.Heal(r.Value) - s.addLog(fmt.Sprintf("%s's relic heals %d HP", p.Name, r.Value)) + s.addLog(fmt.Sprintf("%s์˜ ์œ ๋ฌผ๋กœ HP %d ํšŒ๋ณต", p.Name, r.Value)) } } p.Gold += goldReward + bonus } } - s.addLog(fmt.Sprintf("%s defeated! +%d gold", m.Name, goldReward)) + s.addLog(fmt.Sprintf("%s ์ฒ˜์น˜! +%d ๊ณจ๋“œ", m.Name, goldReward)) if m.IsBoss { s.state.BossKilled = true s.grantBossRelic() @@ -385,7 +385,7 @@ func (s *GameSession) resolvePlayerActions() { // Check if combat is over if len(s.state.Monsters) == 0 { s.state.Floor.Rooms[s.state.Floor.CurrentRoom].Cleared = true - s.addLog("Room cleared!") + s.addLog("๋ฐฉ ํด๋ฆฌ์–ด!") for _, p := range s.state.Players { p.Fled = false } @@ -402,7 +402,7 @@ func (s *GameSession) advanceFloor() { s.state.Phase = PhaseResult s.state.Victory = true s.state.GameOver = true - s.addLog("You conquered the Catacombs!") + s.addLog("์นดํƒ€์ฝค์„ ์ •๋ณตํ–ˆ์Šต๋‹ˆ๋‹ค!") return } // Grant 1 skill point per floor clear @@ -421,11 +421,11 @@ func (s *GameSession) advanceFloor() { } s.state.Phase = PhaseExploring s.state.CombatTurn = 0 - s.addLog(fmt.Sprintf("Descending to B%d...", s.state.FloorNum)) + s.addLog(fmt.Sprintf("B%d์ธต์œผ๋กœ ๋‚ด๋ ค๊ฐ‘๋‹ˆ๋‹ค...", s.state.FloorNum)) for _, p := range s.state.Players { if p.IsDead() { p.Revive(0.30) - s.addLog(fmt.Sprintf("โœฆ %s revived at %d HP!", p.Name, p.HP)) + s.addLog(fmt.Sprintf("โœฆ %s HP %d๋กœ ๋ถ€ํ™œ!", p.Name, p.HP)) } p.Fled = false } @@ -445,7 +445,7 @@ func (s *GameSession) grantBossRelic() { if !p.IsOut() { r := relics[rand.Intn(len(relics))] p.Relics = append(p.Relics, r) - s.addLog(fmt.Sprintf("%s obtained relic: %s", p.Name, r.Name)) + s.addLog(fmt.Sprintf("%s ์œ ๋ฌผ ํš๋“: %s", p.Name, r.Name)) } } } @@ -464,9 +464,9 @@ func (s *GameSession) resolveMonsterActions() { if !p.IsOut() { dmg := combat.CalcDamage(m.ATK, p.EffectiveDEF(), 0.5) p.TakeDamage(dmg) - s.addLog(fmt.Sprintf("%s AoE hits %s for %d dmg", m.Name, p.Name, dmg)) + s.addLog(fmt.Sprintf("%s ๊ด‘์—ญ ๊ณต๊ฒฉ์œผ๋กœ %s์—๊ฒŒ %d ํ”ผํ•ด", m.Name, p.Name, dmg)) if p.IsDead() { - s.addLog(fmt.Sprintf("โ˜  %s has fallen!", p.Name)) + s.addLog(fmt.Sprintf("โ˜  %s ์“ฐ๋Ÿฌ์กŒ์Šต๋‹ˆ๋‹ค!", p.Name)) } } } @@ -477,21 +477,21 @@ func (s *GameSession) resolveMonsterActions() { for _, p := range s.state.Players { if !p.IsOut() { p.AddEffect(entity.ActiveEffect{Type: entity.StatusPoison, Duration: 3, Value: 5}) - s.addLog(fmt.Sprintf("%s poisons %s!", m.Name, p.Name)) + s.addLog(fmt.Sprintf("%s์ด(๊ฐ€) %s์—๊ฒŒ ๋…์„ ๊ฑธ์—ˆ์Šต๋‹ˆ๋‹ค!", m.Name, p.Name)) } } case entity.PatternBurn: for _, p := range s.state.Players { if !p.IsOut() { p.AddEffect(entity.ActiveEffect{Type: entity.StatusBurn, Duration: 2, Value: 8}) - s.addLog(fmt.Sprintf("%s burns %s!", m.Name, p.Name)) + s.addLog(fmt.Sprintf("%s์ด(๊ฐ€) %s์„(๋ฅผ) ๋ถˆํƒœ์› ์Šต๋‹ˆ๋‹ค!", m.Name, p.Name)) } } case entity.PatternFreeze: for _, p := range s.state.Players { if !p.IsOut() { p.AddEffect(entity.ActiveEffect{Type: entity.StatusFreeze, Duration: 1, Value: 0}) - s.addLog(fmt.Sprintf("%s freezes %s!", m.Name, p.Name)) + s.addLog(fmt.Sprintf("%s์ด(๊ฐ€) %s์„(๋ฅผ) ๋™๊ฒฐ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค!", m.Name, p.Name)) } } case entity.PatternHeal: @@ -500,7 +500,7 @@ func (s *GameSession) resolveMonsterActions() { if m.HP > m.MaxHP { m.HP = m.MaxHP } - s.addLog(fmt.Sprintf("%s regenerates %d HP!", m.Name, healAmt)) + s.addLog(fmt.Sprintf("%s HP %d ์žฌ์ƒ!", m.Name, healAmt)) } } } else { @@ -509,20 +509,20 @@ func (s *GameSession) resolveMonsterActions() { if !p.IsOut() { dmg := combat.CalcDamage(m.ATK, p.EffectiveDEF(), 1.0) p.TakeDamage(dmg) - s.addLog(fmt.Sprintf("%s attacks %s for %d dmg", m.Name, p.Name, dmg)) + s.addLog(fmt.Sprintf("%s์ด(๊ฐ€) %s์„(๋ฅผ) ๊ณต๊ฒฉํ•˜์—ฌ %d ํ”ผํ•ด", m.Name, p.Name, dmg)) if m.IsElite { def := entity.ElitePrefixDefs[m.ElitePrefix] if def.OnHit >= 0 { p.AddEffect(entity.ActiveEffect{Type: def.OnHit, Duration: 2, Value: 3}) - s.addLog(fmt.Sprintf("%s's %s effect afflicts %s!", m.Name, def.Name, p.Name)) + s.addLog(fmt.Sprintf("%s์˜ %s ํšจ๊ณผ๊ฐ€ %s์—๊ฒŒ ์ ์šฉ!", m.Name, def.Name, p.Name)) } else if m.ElitePrefix == entity.PrefixVampiric { heal := dmg / 4 m.HP = min(m.HP+heal, m.MaxHP) - s.addLog(fmt.Sprintf("%s drains life from %s! (+%d HP)", m.Name, p.Name, heal)) + s.addLog(fmt.Sprintf("%s์ด(๊ฐ€) %s์˜ ์ƒ๋ช…๋ ฅ์„ ํก์ˆ˜! (+%d HP)", m.Name, p.Name, heal)) } } if p.IsDead() { - s.addLog(fmt.Sprintf("โ˜  %s has fallen!", p.Name)) + s.addLog(fmt.Sprintf("โ˜  %s ์“ฐ๋Ÿฌ์กŒ์Šต๋‹ˆ๋‹ค!", p.Name)) } } } @@ -540,6 +540,6 @@ func (s *GameSession) resolveMonsterActions() { if allPlayersDead { s.state.Phase = PhaseResult s.state.GameOver = true - s.addLog("Party wiped!") + s.addLog("ํŒŒํ‹ฐ๊ฐ€ ์ „๋ฉธํ–ˆ์Šต๋‹ˆ๋‹ค!") } } diff --git a/store/achievements.go b/store/achievements.go index 37c9ead..efc9653 100644 --- a/store/achievements.go +++ b/store/achievements.go @@ -14,16 +14,16 @@ type Achievement struct { } var AchievementDefs = []Achievement{ - {ID: "first_clear", Name: "Dungeon Delver", Description: "Clear floor 5 for the first time"}, - {ID: "boss_slayer", Name: "Boss Slayer", Description: "Defeat any boss"}, - {ID: "floor10", Name: "Deep Explorer", Description: "Reach floor 10"}, - {ID: "floor20", Name: "Conqueror", Description: "Conquer the Catacombs (floor 20)"}, - {ID: "solo_clear", Name: "Lone Wolf", Description: "Clear floor 5 solo"}, - {ID: "gold_hoarder", Name: "Gold Hoarder", Description: "Accumulate 200+ gold in one run"}, - {ID: "no_death", Name: "Untouchable", Description: "Complete a floor without anyone dying"}, - {ID: "full_party", Name: "Fellowship", Description: "Start a game with 4 players"}, - {ID: "relic_collector", Name: "Relic Collector", Description: "Collect 3+ relics in one run"}, - {ID: "flee_master", Name: "Tactical Retreat", Description: "Successfully flee from combat"}, + {ID: "first_clear", Name: "๋˜์ „ ํƒํ—˜๊ฐ€", Description: "์ฒ˜์Œ์œผ๋กœ 5์ธต ํด๋ฆฌ์–ด"}, + {ID: "boss_slayer", Name: "๋ณด์Šค ์Šฌ๋ ˆ์ด์–ด", Description: "๋ณด์Šค ์ฒ˜์น˜"}, + {ID: "floor10", Name: "์‹ฌ์ธต ํƒํ—˜๊ฐ€", Description: "10์ธต ๋„๋‹ฌ"}, + {ID: "floor20", Name: "์ •๋ณต์ž", Description: "์นดํƒ€์ฝค ์ •๋ณต (20์ธต)"}, + {ID: "solo_clear", Name: "์™ธ๋กœ์šด ๋Š‘๋Œ€", Description: "์†”๋กœ๋กœ 5์ธต ํด๋ฆฌ์–ด"}, + {ID: "gold_hoarder", Name: "๊ณจ๋“œ ์ˆ˜์ง‘๊ฐ€", Description: "ํ•œ ๋ฒˆ์˜ ํ”Œ๋ ˆ์ด์—์„œ ๊ณจ๋“œ 200 ์ด์ƒ ๋ชจ์œผ๊ธฐ"}, + {ID: "no_death", Name: "๋ฌด์ ", Description: "์•„๋ฌด๋„ ์ฃฝ์ง€ ์•Š๊ณ  ์ธต ํด๋ฆฌ์–ด"}, + {ID: "full_party", Name: "๋™๋ฃŒ๋“ค", Description: "4๋ช…์œผ๋กœ ๊ฒŒ์ž„ ์‹œ์ž‘"}, + {ID: "relic_collector", Name: "์œ ๋ฌผ ์ˆ˜์ง‘๊ฐ€", Description: "ํ•œ ๋ฒˆ์˜ ํ”Œ๋ ˆ์ด์—์„œ ์œ ๋ฌผ 3๊ฐœ ์ด์ƒ ์ˆ˜์ง‘"}, + {ID: "flee_master", Name: "์ „๋žต์  ํ›„ํ‡ด", Description: "์ „ํˆฌ์—์„œ ๋„์ฃผ ์„ฑ๊ณต"}, } func (d *DB) initAchievements() error { diff --git a/ui/achievements_view.go b/ui/achievements_view.go index 5f1d1e3..5ef9131 100644 --- a/ui/achievements_view.go +++ b/ui/achievements_view.go @@ -33,7 +33,7 @@ func (s *AchievementsScreen) View(ctx *Context) string { } func renderAchievements(playerName string, achievements []store.Achievement, width, height int) string { - title := styleHeader.Render("โ”€โ”€ Achievements โ”€โ”€") + title := styleHeader.Render("โ”€โ”€ ์—…์  โ”€โ”€") var content string unlocked := 0 @@ -49,9 +49,9 @@ func renderAchievements(playerName string, achievements []store.Achievement, wid content += styleSystem.Render(" "+a.Description) + "\n" } - progress := fmt.Sprintf("\n %s", styleGold.Render(fmt.Sprintf("%d/%d Unlocked", unlocked, len(achievements)))) + progress := fmt.Sprintf("\n %s", styleGold.Render(fmt.Sprintf("%d/%d ํ•ด๊ธˆ", unlocked, len(achievements)))) - footer := styleSystem.Render("\n[A] Back") + footer := styleSystem.Render("\n[A] ๋’ค๋กœ") return lipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, lipgloss.JoinVertical(lipgloss.Center, title, "", content, progress, footer)) diff --git a/ui/class_view.go b/ui/class_view.go index 24ea412..813adc3 100644 --- a/ui/class_view.go +++ b/ui/class_view.go @@ -69,10 +69,10 @@ var classOptions = []struct { name string desc string }{ - {entity.ClassWarrior, "Warrior", "HP:120 ATK:12 DEF:8 Skill: Taunt (draw enemy fire)"}, - {entity.ClassMage, "Mage", "HP:70 ATK:20 DEF:3 Skill: Fireball (AoE damage)"}, - {entity.ClassHealer, "Healer", "HP:90 ATK:8 DEF:5 Skill: Heal (restore 30 HP)"}, - {entity.ClassRogue, "Rogue", "HP:85 ATK:15 DEF:4 Skill: Scout (reveal rooms)"}, + {entity.ClassWarrior, "Warrior", "HP:120 ATK:12 DEF:8 ์Šคํ‚ฌ: Taunt (์ ์˜ ๊ณต๊ฒฉ์„ ๋Œ์–ด์˜ด)"}, + {entity.ClassMage, "Mage", "HP:70 ATK:20 DEF:3 ์Šคํ‚ฌ: Fireball (๊ด‘์—ญ ํ”ผํ•ด)"}, + {entity.ClassHealer, "Healer", "HP:90 ATK:8 DEF:5 ์Šคํ‚ฌ: Heal (HP 30 ํšŒ๋ณต)"}, + {entity.ClassRogue, "Rogue", "HP:85 ATK:15 DEF:4 ์Šคํ‚ฌ: Scout (์ฃผ๋ณ€ ๋ฐฉ ํƒ์ƒ‰)"}, } func renderClassSelect(state classSelectState, width, height int) string { @@ -90,7 +90,7 @@ func renderClassSelect(state classSelectState, width, height int) string { descStyle := lipgloss.NewStyle(). Foreground(lipgloss.Color("240")) - header := headerStyle.Render("โ”€โ”€ Choose Your Class โ”€โ”€") + header := headerStyle.Render("โ”€โ”€ ์ง์—…์„ ์„ ํƒํ•˜์„ธ์š” โ”€โ”€") list := "" for i, opt := range classOptions { marker := " " @@ -103,7 +103,7 @@ func renderClassSelect(state classSelectState, width, height int) string { marker, style.Render(opt.name), descStyle.Render(opt.desc)) } - menu := "[Up/Down] Select [Enter] Confirm" + menu := "[Up/Down] ์„ ํƒ [Enter] ํ™•์ธ" return lipgloss.JoinVertical(lipgloss.Left, header, diff --git a/ui/codex_view.go b/ui/codex_view.go index f9ce5e0..8c35906 100644 --- a/ui/codex_view.go +++ b/ui/codex_view.go @@ -71,10 +71,10 @@ func (s *CodexScreen) Update(msg tea.Msg, ctx *Context) (Screen, tea.Cmd) { } func (s *CodexScreen) View(ctx *Context) string { - title := styleHeader.Render("-- Codex --") + title := styleHeader.Render("-- ๋„๊ฐ --") // Tab headers - tabNames := []string{"Monsters", "Items", "Events"} + tabNames := []string{"๋ชฌ์Šคํ„ฐ", "์•„์ดํ…œ", "์ด๋ฒคํŠธ"} var tabs []string for i, name := range tabNames { if i == s.tab { @@ -117,7 +117,7 @@ func (s *CodexScreen) View(ctx *Context) string { } completion := lipgloss.NewStyle().Foreground(colorCyan). - Render(fmt.Sprintf("Discovered: %d/%d (%.0f%%)", count, total, pct)) + Render(fmt.Sprintf("๋ฐœ๊ฒฌ: %d/%d (%.0f%%)", count, total, pct)) // Sort discovered keys for consistent display discoveredKeys := make([]string, 0, len(discovered)) @@ -151,7 +151,7 @@ func (s *CodexScreen) View(ctx *Context) string { } } - footer := styleSystem.Render("[Tab/Left/Right] Switch Tab [Esc] Back") + footer := styleSystem.Render("[Tab/Left/Right] ํƒญ ์ „ํ™˜ [Esc] ๋’ค๋กœ") content := lipgloss.JoinVertical(lipgloss.Center, title, diff --git a/ui/game_view.go b/ui/game_view.go index 9b16617..ff9dd33 100644 --- a/ui/game_view.go +++ b/ui/game_view.go @@ -386,7 +386,7 @@ func renderMap(floor *dungeon.Floor) string { } total := len(floor.Rooms) - header := headerStyle.Render(fmt.Sprintf("โ”€โ”€ Catacombs B%d: %s โ”€โ”€ %d/%d Rooms โ”€โ”€", floor.Number, theme.Name, explored, total)) + header := headerStyle.Render(fmt.Sprintf("โ”€โ”€ ์นดํƒ€์ฝค B%d: %s โ”€โ”€ %d/%d ๋ฐฉ โ”€โ”€", floor.Number, theme.Name, explored, total)) return header + "\n" + dungeon.RenderFloor(floor, floor.CurrentRoom, true) } @@ -401,16 +401,16 @@ func renderHUD(state game.GameState, targetCursor int, moveCursor int, fingerpri hpBar := renderHPBar(p.HP, p.MaxHP, 20) status := "" if p.IsDead() { - status = " [DEAD]" + status = " [์‚ฌ๋ง]" } - sb.WriteString(fmt.Sprintf("%s (%s) %s %d/%d%s Gold: %d", + sb.WriteString(fmt.Sprintf("%s (%s) %s %d/%d%s ๊ณจ๋“œ: %d", p.Name, p.Class, hpBar, p.HP, p.MaxHP, status, p.Gold)) // Show inventory count itemCount := len(p.Inventory) relicCount := len(p.Relics) if itemCount > 0 || relicCount > 0 { - sb.WriteString(fmt.Sprintf(" Items:%d Relics:%d", itemCount, relicCount)) + sb.WriteString(fmt.Sprintf(" ์•„์ดํ…œ:%d ์œ ๋ฌผ:%d", itemCount, relicCount)) } sb.WriteString("\n") } @@ -439,7 +439,7 @@ func renderHUD(state game.GameState, targetCursor int, moveCursor int, fingerpri sb.WriteString("\n") // Action bar - sb.WriteString(styleAction.Render("[1]Attack [2]Skill [3]Item [4]Flee [5]Wait [Tab]Target [/]Chat")) + sb.WriteString(styleAction.Render("[1]๊ณต๊ฒฉ [2]์Šคํ‚ฌ [3]์•„์ดํ…œ [4]๋„์ฃผ [5]๋Œ€๊ธฐ [Tab]๋Œ€์ƒ [/]์ฑ„ํŒ…")) sb.WriteString("\n") // Timer @@ -448,7 +448,7 @@ func renderHUD(state game.GameState, targetCursor int, moveCursor int, fingerpri if remaining < 0 { remaining = 0 } - sb.WriteString(styleTimer.Render(fmt.Sprintf(" Timer: %.1fs", remaining.Seconds()))) + sb.WriteString(styleTimer.Render(fmt.Sprintf(" ํƒ€์ด๋จธ: %.1f์ดˆ", remaining.Seconds()))) sb.WriteString("\n") } @@ -458,15 +458,15 @@ func renderHUD(state game.GameState, targetCursor int, moveCursor int, fingerpri var skillDesc string switch p.Class { case entity.ClassWarrior: - skillDesc = "Skill: Taunt โ€” enemies attack you for 2 turns" + skillDesc = "์Šคํ‚ฌ: Taunt โ€” 2ํ„ด๊ฐ„ ์ ์˜ ๊ณต๊ฒฉ์„ ๋Œ์–ด์˜ด" case entity.ClassMage: - skillDesc = "Skill: Fireball โ€” AoE 0.8x dmg to all enemies" + skillDesc = "์Šคํ‚ฌ: Fireball โ€” ์ „์ฒด ์ ์—๊ฒŒ 0.8๋ฐฐ ํ”ผํ•ด" case entity.ClassHealer: - skillDesc = "Skill: Heal โ€” restore 30 HP to an ally" + skillDesc = "์Šคํ‚ฌ: Heal โ€” ์•„๊ตฐ HP 30 ํšŒ๋ณต" case entity.ClassRogue: - skillDesc = "Skill: Scout โ€” reveal neighboring rooms" + skillDesc = "์Šคํ‚ฌ: Scout โ€” ์ฃผ๋ณ€ ๋ฐฉ ๊ณต๊ฐœ" } - skillDesc += fmt.Sprintf(" (%d uses left)", p.SkillUses) + skillDesc += fmt.Sprintf(" (๋‚จ์€ ํšŸ์ˆ˜: %d)", p.SkillUses) sb.WriteString(styleSystem.Render(skillDesc)) sb.WriteString("\n") break @@ -484,7 +484,7 @@ func renderHUD(state game.GameState, targetCursor int, moveCursor int, fingerpri r := state.Floor.Rooms[n] status := r.Type.String() if r.Cleared { - status = "Cleared" + status = "ํด๋ฆฌ์–ด" } marker := " " style := normalStyle @@ -492,7 +492,7 @@ func renderHUD(state game.GameState, targetCursor int, moveCursor int, fingerpri marker = "> " style = selectedStyle } - sb.WriteString(style.Render(fmt.Sprintf("%sRoom %d: %s", marker, n, status))) + sb.WriteString(style.Render(fmt.Sprintf("%s๋ฐฉ %d: %s", marker, n, status))) sb.WriteString("\n") } } @@ -504,7 +504,7 @@ func renderHUD(state game.GameState, targetCursor int, moveCursor int, fingerpri branches := entity.GetBranches(p.Class) sb.WriteString("\n") skillStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("213")).Bold(true) - sb.WriteString(skillStyle.Render(fmt.Sprintf(" Skill Point Available! (%d unspent)", p.Skills.Points-p.Skills.Allocated))) + sb.WriteString(skillStyle.Render(fmt.Sprintf(" ์Šคํ‚ฌ ํฌ์ธํŠธ ์‚ฌ์šฉ ๊ฐ€๋Šฅ! (๋ฏธ์‚ฌ์šฉ: %d)", p.Skills.Points-p.Skills.Allocated))) sb.WriteString("\n") for i, branch := range branches { key := "[" @@ -513,7 +513,7 @@ func renderHUD(state game.GameState, targetCursor int, moveCursor int, fingerpri } nextNode := p.Skills.Allocated if p.Skills.BranchIndex >= 0 && p.Skills.BranchIndex != i { - sb.WriteString(fmt.Sprintf(" [%s] %s (locked)\n", key, branch.Name)) + sb.WriteString(fmt.Sprintf(" [%s] %s (์ž ๊น€)\n", key, branch.Name)) } else if nextNode < 3 { node := branch.Nodes[nextNode] sb.WriteString(fmt.Sprintf(" [%s] %s -> %s\n", key, branch.Name, node.Name)) @@ -522,7 +522,7 @@ func renderHUD(state game.GameState, targetCursor int, moveCursor int, fingerpri break } } - sb.WriteString("[Up/Down] Select [Enter] Move [Q] Quit") + sb.WriteString("[Up/Down] ์„ ํƒ [Enter] ์ด๋™ [Q] ์ข…๋ฃŒ") } if state.Phase == game.PhaseCombat { @@ -550,19 +550,19 @@ func renderCombatLog(log []string) string { func colorizeLog(msg string) string { switch { - case strings.Contains(msg, "fled"): + case strings.Contains(msg, "๋„์ฃผ"): return styleFlee.Render(msg) - case strings.Contains(msg, "co-op"): + case strings.Contains(msg, "ํ˜‘๋™"): return styleCoop.Render(msg) - case strings.Contains(msg, "healed") || strings.Contains(msg, "Heal") || strings.Contains(msg, "Blessing"): + case strings.Contains(msg, "ํšŒ๋ณต") || strings.Contains(msg, "Heal") || strings.Contains(msg, "์น˜์œ ") || strings.Contains(msg, "๋ถ€ํ™œ"): return styleHeal.Render(msg) - case strings.Contains(msg, "dmg") || strings.Contains(msg, "hit") || strings.Contains(msg, "attacks") || strings.Contains(msg, "Trap"): + case strings.Contains(msg, "ํ”ผํ•ด") || strings.Contains(msg, "๊ณต๊ฒฉ") || strings.Contains(msg, "Trap") || strings.Contains(msg, "ํ•จ์ •"): return styleDamage.Render(msg) - case strings.Contains(msg, "Taunt") || strings.Contains(msg, "scouted"): + case strings.Contains(msg, "Taunt") || strings.Contains(msg, "์ •์ฐฐ"): return styleStatus.Render(msg) - case strings.Contains(msg, "gold") || strings.Contains(msg, "Gold") || strings.Contains(msg, "found"): + case strings.Contains(msg, "๊ณจ๋“œ") || strings.Contains(msg, "Gold") || strings.Contains(msg, "๋ฐœ๊ฒฌ"): return styleGold.Render(msg) - case strings.Contains(msg, "defeated") || strings.Contains(msg, "cleared") || strings.Contains(msg, "Descending"): + case strings.Contains(msg, "์ฒ˜์น˜") || strings.Contains(msg, "ํด๋ฆฌ์–ด") || strings.Contains(msg, "๋‚ด๋ ค๊ฐ‘๋‹ˆ๋‹ค") || strings.Contains(msg, "์ •๋ณต"): return styleSystem.Render(msg) default: return msg @@ -600,14 +600,14 @@ func renderHPBar(current, max, width int) string { func renderPartyPanel(players []*entity.Player, submittedActions map[string]string) string { var sb strings.Builder - sb.WriteString(styleHeader.Render(" PARTY") + "\n\n") + sb.WriteString(styleHeader.Render(" ์•„๊ตฐ") + "\n\n") for _, p := range players { nameStr := stylePlayer.Render(fmt.Sprintf(" โ™ฆ %s", p.Name)) classStr := styleSystem.Render(fmt.Sprintf(" (%s)", p.Class)) status := "" if p.IsDead() { - status = styleDamage.Render(" [DEAD]") + status = styleDamage.Render(" [์‚ฌ๋ง]") } sb.WriteString(nameStr + classStr + status + "\n") @@ -637,7 +637,7 @@ func renderPartyPanel(players []*entity.Player, submittedActions map[string]stri sb.WriteString(styleHeal.Render(fmt.Sprintf(" โœ“ %s", action))) sb.WriteString("\n") } else if !p.IsOut() { - sb.WriteString(styleSystem.Render(" ... Waiting")) + sb.WriteString(styleSystem.Render(" ... ๋Œ€๊ธฐ์ค‘")) sb.WriteString("\n") } sb.WriteString("\n") @@ -647,7 +647,7 @@ func renderPartyPanel(players []*entity.Player, submittedActions map[string]stri func renderEnemyPanel(monsters []*entity.Monster, targetCursor int) string { var sb strings.Builder - sb.WriteString(styleHeader.Render(" ENEMIES") + "\n\n") + sb.WriteString(styleHeader.Render(" ์ ") + "\n\n") for i, m := range monsters { if m.IsDead() { @@ -667,7 +667,7 @@ func renderEnemyPanel(monsters []*entity.Monster, targetCursor int) string { hpBar := renderHPBar(m.HP, m.MaxHP, 12) taunt := "" if m.TauntTarget { - taunt = styleStatus.Render(fmt.Sprintf(" [TAUNTED %dt]", m.TauntTurns)) + taunt = styleStatus.Render(fmt.Sprintf(" [๋„๋ฐœ๋จ %dํ„ด]", m.TauntTurns)) } sb.WriteString(fmt.Sprintf(" %s[%d] %s %s %d/%d%s\n\n", marker, i, styleEnemy.Render(m.Name), hpBar, m.HP, m.MaxHP, taunt)) diff --git a/ui/help_view.go b/ui/help_view.go index 89583da..7e6be66 100644 --- a/ui/help_view.go +++ b/ui/help_view.go @@ -26,38 +26,38 @@ func (s *HelpScreen) View(ctx *Context) string { } func renderHelp(width, height int) string { - title := styleHeader.Render("โ”€โ”€ Controls โ”€โ”€") + title := styleHeader.Render("โ”€โ”€ ์กฐ์ž‘๋ฒ• โ”€โ”€") sections := []struct{ header, body string }{ - {"Lobby", ` [C] Create room [J] Join by code - [Enter] Join selected room - [D] Daily Challenge [H] Hard Mode toggle - [Q] Back to title`}, - {"Exploration", ` [Up/Down] Select room - [Enter] Move to room - [[] / []] Allocate skill point (branch 1/2) - [/] Chat - [Q] Quit`}, - {"Combat (10s per turn)", ` [1] Attack [2] Skill - [3] Use Item [4] Flee - [5] Defend [Tab] Switch Target - [/] Chat`}, - {"Shop", ` [1-3] Buy item - [Q] Leave shop`}, - {"Classes", ` Warrior 120HP 12ATK 8DEF Taunt (draw fire 2t) - Mage 70HP 20ATK 3DEF Fireball (AoE 0.8x) - Healer 90HP 8ATK 5DEF Heal (restore 30HP) - Rogue 85HP 15ATK 4DEF Scout (reveal rooms)`}, - {"Multiplayer", ` โ€ข Up to 4 players per room - โ€ข Co-op bonus: +10% dmg when 2+ target same enemy - โ€ข Class combos trigger bonus effects - โ€ข All players ready โ†’ game starts`}, - {"Tips", ` โ€ข Skills have 3 uses per combat - โ€ข Items are limited to 10 per player - โ€ข Dead players revive next floor at 30% HP - โ€ข Bosses appear at floors 5, 10, 15, 20 - โ€ข Skill points: 1 per floor clear (max 3) - โ€ข Weekly mutations rotate gameplay modifiers`}, + {"๋กœ๋น„", ` [C] ๋ฐฉ ๋งŒ๋“ค๊ธฐ [J] ์ฝ”๋“œ๋กœ ์ฐธ๊ฐ€ + [Enter] ์„ ํƒํ•œ ๋ฐฉ ์ฐธ๊ฐ€ + [D] ์ผ์ผ ๋„์ „ [H] ํ•˜๋“œ ๋ชจ๋“œ ์ „ํ™˜ + [Q] ํƒ€์ดํ‹€๋กœ ๋Œ์•„๊ฐ€๊ธฐ`}, + {"ํƒํ—˜", ` [Up/Down] ๋ฐฉ ์„ ํƒ + [Enter] ๋ฐฉ์œผ๋กœ ์ด๋™ + [[] / []] ์Šคํ‚ฌ ํฌ์ธํŠธ ๋ฐฐ๋ถ„ (๋ถ„๊ธฐ 1/2) + [/] ์ฑ„ํŒ… + [Q] ์ข…๋ฃŒ`}, + {"์ „ํˆฌ (ํ„ด๋‹น 10์ดˆ)", ` [1] ๊ณต๊ฒฉ [2] ์Šคํ‚ฌ + [3] ์•„์ดํ…œ ์‚ฌ์šฉ [4] ๋„์ฃผ + [5] ๋ฐฉ์–ด [Tab] ๋Œ€์ƒ ๋ณ€๊ฒฝ + [/] ์ฑ„ํŒ…`}, + {"์ƒ์ ", ` [1-3] ์•„์ดํ…œ ๊ตฌ๋งค + [Q] ์ƒ์  ๋‚˜๊ฐ€๊ธฐ`}, + {"์ง์—…", ` Warrior 120HP 12ATK 8DEF Taunt (2ํ„ด๊ฐ„ ์  ๊ณต๊ฒฉ ์œ ๋„) + Mage 70HP 20ATK 3DEF Fireball (๊ด‘์—ญ 0.8๋ฐฐ) + Healer 90HP 8ATK 5DEF Heal (HP 30 ํšŒ๋ณต) + Rogue 85HP 15ATK 4DEF Scout (์ฃผ๋ณ€ ๋ฐฉ ๊ณต๊ฐœ)`}, + {"๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด", ` โ€ข ๋ฐฉ๋‹น ์ตœ๋Œ€ 4๋ช… + โ€ข ํ˜‘๋™ ๋ณด๋„ˆ์Šค: 2๋ช… ์ด์ƒ์ด ๊ฐ™์€ ์  ๊ณต๊ฒฉ ์‹œ ํ”ผํ•ด +10% + โ€ข ์ง์—… ์ฝค๋ณด๋กœ ์ถ”๊ฐ€ ํšจ๊ณผ ๋ฐœ๋™ + โ€ข ๋ชจ๋“  ํ”Œ๋ ˆ์ด์–ด ์ค€๋น„ ์™„๋ฃŒ ์‹œ ๊ฒŒ์ž„ ์‹œ์ž‘`}, + {"ํŒ", ` โ€ข ์Šคํ‚ฌ์€ ์ „ํˆฌ๋‹น 3ํšŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ + โ€ข ์•„์ดํ…œ์€ ํ”Œ๋ ˆ์ด์–ด๋‹น 10๊ฐœ ์ œํ•œ + โ€ข ์‚ฌ๋งํ•œ ํ”Œ๋ ˆ์ด์–ด๋Š” ๋‹ค์Œ ์ธต์—์„œ HP 30%๋กœ ๋ถ€ํ™œ + โ€ข ๋ณด์Šค๋Š” 5, 10, 15, 20์ธต์— ๋“ฑ์žฅ + โ€ข ์Šคํ‚ฌ ํฌ์ธํŠธ: ์ธต ํด๋ฆฌ์–ด๋‹น 1ํฌ์ธํŠธ (์ตœ๋Œ€ 3) + โ€ข ์ฃผ๊ฐ„ ๋ณ€์ด๊ฐ€ ๊ฒŒ์ž„ํ”Œ๋ ˆ์ด๋ฅผ ๋ณ€๊ฒฝ`}, } var content string @@ -69,7 +69,7 @@ func renderHelp(width, height int) string { content += bodyStyle.Render(s.body) + "\n\n" } - footer := styleSystem.Render("[H] Back") + footer := styleSystem.Render("[H] ๋’ค๋กœ") return lipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, lipgloss.JoinVertical(lipgloss.Center, title, "", content, footer)) diff --git a/ui/leaderboard_view.go b/ui/leaderboard_view.go index 0f2bb36..f7e4263 100644 --- a/ui/leaderboard_view.go +++ b/ui/leaderboard_view.go @@ -43,10 +43,10 @@ func (s *LeaderboardScreen) View(ctx *Context) string { } func renderLeaderboard(byFloor, byGold []store.RunRecord, daily []store.DailyRecord, tab, width, height int) string { - title := styleHeader.Render("โ”€โ”€ Leaderboard โ”€โ”€") + title := styleHeader.Render("โ”€โ”€ ๋ฆฌ๋”๋ณด๋“œ โ”€โ”€") // Tab header - tabs := []string{"Floor", "Gold", "Daily"} + tabs := []string{"์ธต์ˆ˜", "๊ณจ๋“œ", "์ผ์ผ"} var tabLine string for i, t := range tabs { if i == tab { @@ -60,7 +60,7 @@ func renderLeaderboard(byFloor, byGold []store.RunRecord, daily []store.DailyRec switch tab { case 0: // By Floor - content += styleCoop.Render(" Top by Floor") + "\n" + content += styleCoop.Render(" ์ธต์ˆ˜ ์ˆœ์œ„") + "\n" for i, r := range byFloor { if i >= 10 { break @@ -75,7 +75,7 @@ func renderLeaderboard(byFloor, byGold []store.RunRecord, daily []store.DailyRec r.Floor, styleGold.Render(fmt.Sprintf("%dg", r.Score))) } case 1: // By Gold - content += styleCoop.Render(" Top by Gold") + "\n" + content += styleCoop.Render(" ๊ณจ๋“œ ์ˆœ์œ„") + "\n" for i, r := range byGold { if i >= 10 { break @@ -90,9 +90,9 @@ func renderLeaderboard(byFloor, byGold []store.RunRecord, daily []store.DailyRec r.Floor, styleGold.Render(fmt.Sprintf("%dg", r.Score))) } case 2: // Daily - content += styleCoop.Render(fmt.Sprintf(" Daily Challenge โ€” %s", time.Now().Format("2006-01-02"))) + "\n" + content += styleCoop.Render(fmt.Sprintf(" ์ผ์ผ ๋„์ „ โ€” %s", time.Now().Format("2006-01-02"))) + "\n" if len(daily) == 0 { - content += " No daily runs yet today.\n" + content += " ์˜ค๋Š˜ ์ผ์ผ ๋„์ „ ๊ธฐ๋ก์ด ์—†์Šต๋‹ˆ๋‹ค.\n" } for i, r := range daily { if i >= 20 { @@ -105,7 +105,7 @@ func renderLeaderboard(byFloor, byGold []store.RunRecord, daily []store.DailyRec } } - footer := styleSystem.Render("\n[Tab] Switch Tab [L] Back") + footer := styleSystem.Render("\n[Tab] ํƒญ ์ „ํ™˜ [L] ๋’ค๋กœ") return lipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, lipgloss.JoinVertical(lipgloss.Center, title, tabLine, "", content, footer)) diff --git a/ui/lobby_view.go b/ui/lobby_view.go index 3a572e8..5d59181 100644 --- a/ui/lobby_view.go +++ b/ui/lobby_view.go @@ -54,9 +54,9 @@ func (s *LobbyScreen) refreshLobby(ctx *Context) { rooms := ctx.Lobby.ListRooms() s.rooms = make([]roomInfo, len(rooms)) for i, r := range rooms { - status := "Waiting" + status := "๋Œ€๊ธฐ์ค‘" if r.Status == game.RoomPlaying { - status = "Playing" + status = "์ง„ํ–‰์ค‘" } players := make([]playerInfo, len(r.Players)) for j, p := range r.Players { @@ -108,7 +108,7 @@ func (s *LobbyScreen) Update(msg tea.Msg, ctx *Context) (Screen, tea.Cmd) { // Normal lobby key handling if isKey(key, "c") { if ctx.Lobby != nil { - code := ctx.Lobby.CreateRoom(ctx.PlayerName + "'s Room") + code := ctx.Lobby.CreateRoom(ctx.PlayerName + "์˜ ๋ฐฉ") ctx.Lobby.JoinRoom(code, ctx.PlayerName, ctx.Fingerprint) ctx.RoomCode = code return NewClassSelectScreen(), nil @@ -135,7 +135,7 @@ func (s *LobbyScreen) Update(msg tea.Msg, ctx *Context) (Screen, tea.Cmd) { } else if isKey(key, "d") { // Daily Challenge: create a private solo daily session if ctx.Lobby != nil { - code := ctx.Lobby.CreateRoom(ctx.PlayerName + "'s Daily") + code := ctx.Lobby.CreateRoom(ctx.PlayerName + "์˜ ์ผ์ผ ๋„์ „") if err := ctx.Lobby.JoinRoom(code, ctx.PlayerName, ctx.Fingerprint); err == nil { ctx.RoomCode = code room := ctx.Lobby.GetRoom(code) @@ -200,14 +200,14 @@ func renderLobby(state lobbyState, width, height int) string { Border(lipgloss.RoundedBorder()). Padding(0, 1) - header := headerStyle.Render(fmt.Sprintf("โ”€โ”€ Lobby โ”€โ”€ %d online โ”€โ”€", state.online)) - menu := "[C] Create Room [J] Join by Code [D] Daily Challenge [Up/Down] Select [Enter] Join [Q] Back" + header := headerStyle.Render(fmt.Sprintf("โ”€โ”€ ๋กœ๋น„ โ”€โ”€ %d๋ช… ์ ‘์†์ค‘ โ”€โ”€", state.online)) + menu := "[C] ๋ฐฉ ๋งŒ๋“ค๊ธฐ [J] ์ฝ”๋“œ๋กœ ์ฐธ๊ฐ€ [D] ์ผ์ผ ๋„์ „ [Up/Down] ์„ ํƒ [Enter] ์ฐธ๊ฐ€ [Q] ๋’ค๋กœ" if state.hardUnlocked { hardStatus := "OFF" if state.hardMode { hardStatus = "ON" } - menu += fmt.Sprintf(" [H] Hard Mode: %s", hardStatus) + menu += fmt.Sprintf(" [H] ํ•˜๋“œ ๋ชจ๋“œ: %s", hardStatus) } roomList := "" @@ -234,11 +234,11 @@ func renderLobby(state lobbyState, width, height int) string { } } if roomList == "" { - roomList = " No rooms available. Create one!" + roomList = " ๋ฐฉ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ ๋งŒ๋“œ์„ธ์š”!" } if state.joining { inputStr := state.codeInput + strings.Repeat("_", 4-len(state.codeInput)) - roomList += fmt.Sprintf("\n Enter room code: [%s] (Esc to cancel)\n", inputStr) + roomList += fmt.Sprintf("\n ๋ฐฉ ์ฝ”๋“œ ์ž…๋ ฅ: [%s] (Esc๋กœ ์ทจ์†Œ)\n", inputStr) } return lipgloss.JoinVertical(lipgloss.Left, diff --git a/ui/nickname_view.go b/ui/nickname_view.go index 01e051c..b5563db 100644 --- a/ui/nickname_view.go +++ b/ui/nickname_view.go @@ -39,7 +39,7 @@ func (s *NicknameScreen) Update(msg tea.Msg, ctx *Context) (Screen, tea.Cmd) { gs := NewGameScreen() gs.gameState = ctx.Session.GetState() ctx.Session.TouchActivity(ctx.Fingerprint) - ctx.Session.SendChat("System", ctx.PlayerName+" reconnected!") + ctx.Session.SendChat("System", ctx.PlayerName+" ์žฌ์ ‘์†!") return gs, gs.pollState() } } @@ -66,7 +66,7 @@ func (s *NicknameScreen) View(ctx *Context) string { } func renderNickname(input string, width, height int) string { - title := styleHeader.Render("โ”€โ”€ Enter Your Name โ”€โ”€") + title := styleHeader.Render("โ”€โ”€ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š” โ”€โ”€") display := input if display == "" { @@ -81,8 +81,8 @@ func renderNickname(input string, width, height int) string { Padding(0, 2). Render(stylePlayer.Render(display)) - hint := styleSystem.Render(fmt.Sprintf("(%d/12 characters)", len(input))) - footer := styleAction.Render("[Enter] Confirm [Esc] Cancel") + hint := styleSystem.Render(fmt.Sprintf("(%d/12 ๊ธ€์ž)", len(input))) + footer := styleAction.Render("[Enter] ํ™•์ธ [Esc] ์ทจ์†Œ") return lipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, lipgloss.JoinVertical(lipgloss.Center, title, "", inputBox, hint, "", footer)) diff --git a/ui/result_view.go b/ui/result_view.go index 302810a..d765233 100644 --- a/ui/result_view.go +++ b/ui/result_view.go @@ -56,30 +56,30 @@ func renderResult(state game.GameState, rankings []store.RunRecord) string { // Title if state.Victory { - sb.WriteString(styleHeal.Render(" โœฆ VICTORY โœฆ ") + "\n\n") - sb.WriteString(styleSystem.Render(" You conquered the Catacombs!") + "\n\n") + sb.WriteString(styleHeal.Render(" โœฆ ์Šน๋ฆฌ โœฆ ") + "\n\n") + sb.WriteString(styleSystem.Render(" ์นดํƒ€์ฝค์„ ์ •๋ณตํ–ˆ์Šต๋‹ˆ๋‹ค!") + "\n\n") } else { - sb.WriteString(styleDamage.Render(" โœฆ DEFEAT โœฆ ") + "\n\n") - sb.WriteString(styleSystem.Render(fmt.Sprintf(" Fallen on floor B%d", state.FloorNum)) + "\n\n") + sb.WriteString(styleDamage.Render(" โœฆ ํŒจ๋ฐฐ โœฆ ") + "\n\n") + sb.WriteString(styleSystem.Render(fmt.Sprintf(" B%d์ธต์—์„œ ์“ฐ๋Ÿฌ์กŒ์Šต๋‹ˆ๋‹ค", state.FloorNum)) + "\n\n") } // Player summary - sb.WriteString(styleHeader.Render("โ”€โ”€ Party Summary โ”€โ”€") + "\n\n") + sb.WriteString(styleHeader.Render("โ”€โ”€ ํŒŒํ‹ฐ ์š”์•ฝ โ”€โ”€") + "\n\n") totalGold := 0 for _, p := range state.Players { - status := styleHeal.Render("Alive") + status := styleHeal.Render("์ƒ์กด") if p.IsDead() { - status = styleDamage.Render("Dead") + status = styleDamage.Render("์‚ฌ๋ง") } - sb.WriteString(fmt.Sprintf(" %s (%s) %s Gold: %d Items: %d Relics: %d\n", + sb.WriteString(fmt.Sprintf(" %s (%s) %s ๊ณจ๋“œ: %d ์•„์ดํ…œ: %d ์œ ๋ฌผ: %d\n", stylePlayer.Render(p.Name), p.Class, status, p.Gold, len(p.Inventory), len(p.Relics))) totalGold += p.Gold } - sb.WriteString(fmt.Sprintf("\n Total Gold: %s\n", styleGold.Render(fmt.Sprintf("%d", totalGold)))) + sb.WriteString(fmt.Sprintf("\n ์ด ๊ณจ๋“œ: %s\n", styleGold.Render(fmt.Sprintf("%d", totalGold)))) // Rankings if len(rankings) > 0 { - sb.WriteString("\n" + styleHeader.Render("โ”€โ”€ Top Runs โ”€โ”€") + "\n\n") + sb.WriteString("\n" + styleHeader.Render("โ”€โ”€ ์ตœ๊ณ  ๊ธฐ๋ก โ”€โ”€") + "\n\n") for i, r := range rankings { medal := " " switch i { @@ -90,11 +90,11 @@ func renderResult(state game.GameState, rankings []store.RunRecord) string { case 2: medal = styleGold.Render("๐Ÿฅ‰") } - sb.WriteString(fmt.Sprintf(" %s %s Floor B%d Score: %d\n", medal, r.Player, r.Floor, r.Score)) + sb.WriteString(fmt.Sprintf(" %s %s B%d์ธต ์ ์ˆ˜: %d\n", medal, r.Player, r.Floor, r.Score)) } } - sb.WriteString("\n" + styleAction.Render(" [Enter] Return to Lobby") + "\n") + sb.WriteString("\n" + styleAction.Render(" [Enter] ๋กœ๋น„๋กœ ๋Œ์•„๊ฐ€๊ธฐ") + "\n") return sb.String() } diff --git a/ui/shop_view.go b/ui/shop_view.go index 727ae76..426dcd0 100644 --- a/ui/shop_view.go +++ b/ui/shop_view.go @@ -27,13 +27,13 @@ func (s *ShopScreen) Update(msg tea.Msg, ctx *Context) (Screen, tea.Cmd) { idx := int(key.String()[0] - '1') switch ctx.Session.BuyItem(ctx.Fingerprint, idx) { case game.BuyOK: - s.shopMsg = "Purchased!" + s.shopMsg = "๊ตฌ๋งค ์™„๋ฃŒ!" case game.BuyNoGold: - s.shopMsg = "Not enough gold!" + s.shopMsg = "๊ณจ๋“œ๊ฐ€ ๋ถ€์กฑํ•ฉ๋‹ˆ๋‹ค!" case game.BuyInventoryFull: - s.shopMsg = "Inventory full!" + s.shopMsg = "์ธ๋ฒคํ† ๋ฆฌ๊ฐ€ ๊ฐ€๋“ ์ฐผ์Šต๋‹ˆ๋‹ค!" default: - s.shopMsg = "Cannot buy that!" + s.shopMsg = "๊ตฌ๋งคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค!" } s.gameState = ctx.Session.GetState() } @@ -76,23 +76,23 @@ func renderShop(state game.GameState, width, height int, shopMsg string) string Foreground(lipgloss.Color("196")). Bold(true) - header := headerStyle.Render("โ”€โ”€ Shop โ”€โ”€") + header := headerStyle.Render("โ”€โ”€ ์ƒ์  โ”€โ”€") // Show current player's gold goldLine := "" for _, p := range state.Players { inventoryCount := len(p.Inventory) - goldLine += goldStyle.Render(fmt.Sprintf(" %s โ€” Gold: %d Items: %d/10", p.Name, p.Gold, inventoryCount)) + goldLine += goldStyle.Render(fmt.Sprintf(" %s โ€” ๊ณจ๋“œ: %d ์•„์ดํ…œ: %d/10", p.Name, p.Gold, inventoryCount)) goldLine += "\n" } items := "" for i, item := range state.ShopItems { label := itemTypeLabel(item) - items += fmt.Sprintf(" [%d] %s %s โ€” %d gold\n", i+1, item.Name, label, item.Price) + items += fmt.Sprintf(" [%d] %s %s โ€” %d ๊ณจ๋“œ\n", i+1, item.Name, label, item.Price) } - menu := "[1-3] Buy [Q] Leave Shop" + menu := "[1-3] ๊ตฌ๋งค [Q] ์ƒ์  ๋‚˜๊ฐ€๊ธฐ" parts := []string{header, "", goldLine, items, "", menu} if shopMsg != "" { diff --git a/ui/stats_view.go b/ui/stats_view.go index 9f3ba55..f0757ae 100644 --- a/ui/stats_view.go +++ b/ui/stats_view.go @@ -33,22 +33,22 @@ func (s *StatsScreen) View(ctx *Context) string { } func renderStats(playerName string, stats store.PlayerStats, width, height int) string { - title := styleHeader.Render("โ”€โ”€ Player Statistics โ”€โ”€") + title := styleHeader.Render("โ”€โ”€ ํ”Œ๋ ˆ์ด์–ด ํ†ต๊ณ„ โ”€โ”€") var content string content += stylePlayer.Render(fmt.Sprintf(" %s", playerName)) + "\n\n" - content += fmt.Sprintf(" Total Runs: %s\n", styleGold.Render(fmt.Sprintf("%d", stats.TotalRuns))) - content += fmt.Sprintf(" Best Floor: %s\n", styleGold.Render(fmt.Sprintf("B%d", stats.BestFloor))) - content += fmt.Sprintf(" Total Gold: %s\n", styleGold.Render(fmt.Sprintf("%d", stats.TotalGold))) - content += fmt.Sprintf(" Victories: %s\n", styleHeal.Render(fmt.Sprintf("%d", stats.Victories))) + content += fmt.Sprintf(" ์ด ํ”Œ๋ ˆ์ด: %s\n", styleGold.Render(fmt.Sprintf("%d", stats.TotalRuns))) + content += fmt.Sprintf(" ์ตœ๊ณ  ์ธต: %s\n", styleGold.Render(fmt.Sprintf("B%d", stats.BestFloor))) + content += fmt.Sprintf(" ์ด ๊ณจ๋“œ: %s\n", styleGold.Render(fmt.Sprintf("%d", stats.TotalGold))) + content += fmt.Sprintf(" ์Šน๋ฆฌ ํšŸ์ˆ˜: %s\n", styleHeal.Render(fmt.Sprintf("%d", stats.Victories))) winRate := 0.0 if stats.TotalRuns > 0 { winRate = float64(stats.Victories) / float64(stats.TotalRuns) * 100 } - content += fmt.Sprintf(" Win Rate: %s\n", styleSystem.Render(fmt.Sprintf("%.1f%%", winRate))) + content += fmt.Sprintf(" ์Šน๋ฅ : %s\n", styleSystem.Render(fmt.Sprintf("%.1f%%", winRate))) - footer := styleSystem.Render("[S] Back") + footer := styleSystem.Render("[S] ๋’ค๋กœ") return lipgloss.Place(width, height, lipgloss.Center, lipgloss.Center, lipgloss.JoinVertical(lipgloss.Center, title, "", content, "", footer)) diff --git a/ui/title.go b/ui/title.go index bea4b58..e4a59ee 100644 --- a/ui/title.go +++ b/ui/title.go @@ -44,7 +44,7 @@ func (s *TitleScreen) Update(msg tea.Msg, ctx *Context) (Screen, tea.Cmd) { gs := NewGameScreen() gs.gameState = ctx.Session.GetState() ctx.Session.TouchActivity(ctx.Fingerprint) - ctx.Session.SendChat("System", ctx.PlayerName+" reconnected!") + ctx.Session.SendChat("System", ctx.PlayerName+" ์žฌ์ ‘์†!") return gs, gs.pollState() } } @@ -101,7 +101,7 @@ func renderTitle(width, height int) string { subtitle := lipgloss.NewStyle(). Foreground(colorGray). - Render("โš” A Cooperative Dungeon Crawler โš”") + Render("โš” ํ˜‘๋™ ๋˜์ „ ํฌ๋กค๋Ÿฌ โš”") server := lipgloss.NewStyle(). Foreground(colorCyan). @@ -110,7 +110,7 @@ func renderTitle(width, height int) string { menu := lipgloss.NewStyle(). Foreground(colorWhite). Bold(true). - Render("[Enter] Start [H] Help [S] Stats [A] Achievements [L] Leaderboard [C] Codex [Q] Quit") + Render("[Enter] ์‹œ์ž‘ [H] ๋„์›€๋ง [S] ํ†ต๊ณ„ [A] ์—…์  [L] ๋ฆฌ๋”๋ณด๋“œ [C] ๋„๊ฐ [Q] ์ข…๋ฃŒ") content := lipgloss.JoinVertical(lipgloss.Center, logo, diff --git a/ui/waiting_view.go b/ui/waiting_view.go index 29f76a1..65e4998 100644 --- a/ui/waiting_view.go +++ b/ui/waiting_view.go @@ -83,7 +83,7 @@ func (s *WaitingScreen) View(ctx *Context) string { notReadyStyle := lipgloss.NewStyle(). Foreground(lipgloss.Color("240")) - header := headerStyle.Render(fmt.Sprintf("โ”€โ”€ Waiting Room [%s] โ”€โ”€", ctx.RoomCode)) + header := headerStyle.Render(fmt.Sprintf("โ”€โ”€ ๋Œ€๊ธฐ์‹ค [%s] โ”€โ”€", ctx.RoomCode)) playerList := "" if ctx.Lobby != nil { @@ -92,7 +92,7 @@ func (s *WaitingScreen) View(ctx *Context) string { for _, p := range room.Players { status := notReadyStyle.Render("...") if p.Ready { - status = readyStyle.Render("READY") + status = readyStyle.Render("์ค€๋น„ ์™„๋ฃŒ") } cls := p.Class if cls == "" { @@ -103,11 +103,11 @@ func (s *WaitingScreen) View(ctx *Context) string { } } - menu := "[Enter] Ready" + menu := "[Enter] ์ค€๋น„" if s.ready { - menu = "Waiting for other players..." + menu = "๋‹ค๋ฅธ ํ”Œ๋ ˆ์ด์–ด๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ค‘..." } - menu += " [Esc] Leave" + menu += " [Esc] ๋‚˜๊ฐ€๊ธฐ" return lipgloss.JoinVertical(lipgloss.Left, header,