package game import "fmt" // potions.c — functions for dealing with potions. // pact describes a standard fuse-based potion (potions.c PACT). type pact struct { flags CreatureFlags daemon DaemonID time int high string // message when hallucinating straight string } // pActions is potions.c p_actions[]. The P_SEEINVIS message is dynamic // (it names the fruit) and is computed in doPot. var pActions = [MaxPotions]pact{ PConfuse: {IsHuh, DUnconfuse, HuhDuration, "what a tripy feeling!", "wait, what's going on here. Huh? What? Who?"}, PLSD: {IsHalu, DComeDown, SeeDuration, "Oh, wow! Everything seems so cosmic!", "Oh, wow! Everything seems so cosmic!"}, PSeeInvis: {CanSee, DUnsee, SeeDuration, "", ""}, PBlind: {IsBlind, DSight, SeeDuration, "oh, bummer! Everything is dark! Help!", "a cloak of darkness falls around you"}, PLevit: {IsLevit, DLand, HealTime, "oh, wow! You're floating in the air!", "you start to float in the air"}, } // quaff drinks a potion from the pack (potions.c quaff). func (g *RogueGame) quaff() { p := &g.Player obj := g.getItem("quaff", int(Potion)) // Make certain that it is something that we want to drink if obj == nil { return } if obj.Type != Potion { if !g.Options.Terse { g.msg("yuk! Why would you want to drink that?") } else { g.msg("that's undrinkable") } return } if obj == p.CurWeapon { p.CurWeapon = nil } // Calculate the effect it has on the poor guy. trip := p.On(IsHalu) g.leavePack(obj, false, false) switch obj.Which { case PConfuse: g.doPot(PConfuse, !trip) case PPoison: g.Items.Potions[PPoison].Know = true if p.IsWearing(RSustStr) { g.msg("you feel momentarily sick") } else { g.chgStr(-(g.rnd(3) + 1)) g.msg("you feel very sick now") g.comeDown(0) } case PHealing: g.Items.Potions[PHealing].Know = true if p.Stats.HP += g.roll(p.Stats.Lvl, 4); p.Stats.HP > p.Stats.MaxHP { p.Stats.MaxHP++ p.Stats.HP = p.Stats.MaxHP } g.sight(0) g.msg("you begin to feel better") case PStrength: g.Items.Potions[PStrength].Know = true g.chgStr(1) g.msg("you feel stronger, now. What bulging muscles!") case PMFind: p.Flags.Set(SeeMonst) g.Fuse(DTurnSee, 1, HuhDuration, After) if !g.turnSee(false) { g.msg("you have a %s feeling for a moment, then it passes", g.chooseStr("normal", "strange")) } case PTFind: // Potion of magic detection. Show the potions and scrolls show := false if len(g.Level.Objects) > 0 { g.scr.Hw.Clear() for _, tp := range g.Level.Objects { if tp.isMagic() { show = true g.scr.Hw.MvAddCh(tp.Pos.Y, tp.Pos.X, Magic) g.Items.Potions[PTFind].Know = true } } for _, mp := range g.Level.Monsters { for _, tp := range mp.Pack { if tp.isMagic() { show = true g.scr.Hw.MvAddCh(mp.Pos.Y, mp.Pos.X, Magic) } } } } if show { g.Items.Potions[PTFind].Know = true g.showWin("You sense the presence of magic on this level.--More--") } else { g.msg("you have a %s feeling for a moment, then it passes", g.chooseStr("normal", "strange")) } case PLSD: if !trip { if p.On(SeeMonst) { g.turnSee(false) } g.StartDaemon(DVisuals, 0, Before) g.SeenStairs = g.seenStairs() } g.doPot(PLSD, true) case PSeeInvis: show := p.On(CanSee) g.doPot(PSeeInvis, false) if !show { g.invisOn() } g.sight(0) case PRaise: g.Items.Potions[PRaise].Know = true g.msg("you suddenly feel much more skillful") g.raiseLevel() case PXHeal: g.Items.Potions[PXHeal].Know = true if p.Stats.HP += g.roll(p.Stats.Lvl, 8); p.Stats.HP > p.Stats.MaxHP { if p.Stats.HP > p.Stats.MaxHP+p.Stats.Lvl+1 { p.Stats.MaxHP++ } p.Stats.MaxHP++ p.Stats.HP = p.Stats.MaxHP } g.sight(0) g.comeDown(0) g.msg("you begin to feel much better") case PHaste: g.Items.Potions[PHaste].Know = true g.After = false if g.addHaste(true) { g.msg("you feel yourself moving much faster") } case PRestore: if p.IsRing(Left, RAddStr) { addStr(&p.Stats.Str, -p.CurRing[Left].Arm) } if p.IsRing(Right, RAddStr) { addStr(&p.Stats.Str, -p.CurRing[Right].Arm) } if p.Stats.Str < p.MaxStats.Str { p.Stats.Str = p.MaxStats.Str } if p.IsRing(Left, RAddStr) { addStr(&p.Stats.Str, p.CurRing[Left].Arm) } if p.IsRing(Right, RAddStr) { addStr(&p.Stats.Str, p.CurRing[Right].Arm) } g.msg("hey, this tastes great. It make you feel warm all over") case PBlind: g.doPot(PBlind, true) case PLevit: g.doPot(PLevit, true) } g.status() // Throw the item away g.callIt(&g.Items.Potions[obj.Which]) } // raiseLevel: the guy just magically went up a level (potions.c // raise_level). func (g *RogueGame) raiseLevel() { g.Player.Stats.Exp = eLevels[g.Player.Stats.Lvl-1] + 1 g.checkLevel() } // doPot does a potion with standard setup: it uses a fuse and turns on a // flag (potions.c do_pot). func (g *RogueGame) doPot(typ int, knowit bool) { pp := &pActions[typ] if !g.Items.Potions[typ].Know { g.Items.Potions[typ].Know = knowit } t := g.spread(pp.time) if !g.Player.On(pp.flags) { g.Player.Flags.Set(pp.flags) g.Fuse(pp.daemon, 0, t, After) g.look(false) } else { g.Lengthen(pp.daemon, t) } high, straight := pp.high, pp.straight if typ == PSeeInvis { s := fmt.Sprintf("this potion tastes like %s juice", g.Fruit) high, straight = s, s } g.msg("%s", g.chooseStr(high, straight)) } // isMagic reports whether an object radiates magic (potions.c is_magic). func (o *Object) isMagic() bool { switch o.Type { case Armor: return o.Flags.Has(IsProt) || o.Arm != aClass[o.Which] case Weapon: return o.HPlus != 0 || o.DPlus != 0 case Potion, Scroll, Stick, Ring, Amulet: return true } return false } // invisOn turns on the ability to see invisible monsters (potions.c // invis_on). func (g *RogueGame) invisOn() { g.Player.Flags.Set(CanSee) for _, mp := range g.Level.Monsters { if mp.On(IsInvis) && g.seeMonst(mp) && !g.Player.On(IsHalu) { g.mvaddch(mp.Pos.Y, mp.Pos.X, mp.Disguise) } } } // turnSee puts on or off seeing monsters on this level (potions.c // turn_see). func (g *RogueGame) turnSee(turnOff bool) bool { addNew := false for _, mp := range g.Level.Monsters { g.move(mp.Pos.Y, mp.Pos.X) canSee := g.seeMonst(mp) if turnOff { if !canSee { g.addch(mp.OldCh) } } else { if !canSee { g.standout() } if !g.Player.On(IsHalu) { g.addch(mp.Type) } else { g.addch(byte(g.rnd(26) + 'A')) } if !canSee { g.standend() addNew = true } } } if turnOff { g.Player.Flags.Clear(SeeMonst) } else { g.Player.Flags.Set(SeeMonst) } return addNew } // seenStairs reports whether the player has seen the stairs (potions.c // seen_stairs). func (g *RogueGame) seenStairs() bool { st := g.Level.Stairs g.move(st.Y, st.X) if g.inch() == Stairs { // it's on the map return true } if g.Player.Pos == st { // it's under him return true } // if a monster is on the stairs, this gets hairy if tp := g.Level.MonsterAt(st.Y, st.X); tp != nil { if g.seeMonst(tp) && tp.On(IsRun) { // visible and awake: return true // it must have moved there } if g.Player.On(SeeMonst) && tp.OldCh == Stairs { return true } } return false }