// Package game is a Go port of Rogue 5.4.4 ("Exploring the Dungeons of // Doom", Michael Toy, Ken Arnold and Glenn Wichman, 1980-1999). // // The port is function-by-function faithful to the C sources kept in the // repository root; ARCHITECTURE.md documents both the original program and // the design of this port. All formerly-global state lives on the RogueGame // type. package game // Maximum number of different things (rogue.h) const ( MaxRooms = 9 MaxThings = 9 MaxObj = 9 MaxPack = 23 MaxTraps = 10 AmuletLevel = 26 NumThings = 7 // number of types of things MaxPass = 13 // upper limit on number of passages NumLines = 24 NumCols = 80 StatLine = NumLines - 1 BoreLevel = 50 MaxStr = 1024 // maximum length of strings MaxLines = 32 // maximum number of screen lines used MaxCols = 80 // maximum number of screen columns used ) // Return values for get functions (rogue.h) const ( Norm = 0 // normal exit Quit = 1 // quit option setting Minus = 2 // back up one option ) // Inventory types (rogue.h) const ( InvOver = 0 InvSlow = 1 InvClear = 2 ) // Things that appear on the screens (rogue.h). These byte values serve both // as map characters and as Object.Type discriminators, exactly as in C. const ( Passage byte = '#' Door byte = '+' Floor byte = '.' PlayerCh byte = '@' Trap byte = '^' Stairs byte = '%' Gold byte = '*' Potion byte = '!' Scroll byte = '?' Magic byte = '$' Food byte = ':' Weapon byte = ')' Armor byte = ']' Amulet byte = ',' Ring byte = '=' Stick byte = '/' ) // Various constants (rogue.h) const ( HealTime = 30 HuhDuration = 20 SeeDuration = 850 HungerTime = 1300 MoreTime = 150 StomachSize = 2000 StarveTime = 850 Escape = 27 Left = 0 Right = 1 BoltLength = 6 LampDist = 3 MaxDaemons = 20 MaxInp = 50 // options.c: max string entered by the user MaxNameLen = 40 // init.c MAXNAME: max chars in a generated scroll name ) // Save against things (rogue.h) const ( VsPoison = 0 VsParalyzation = 0 VsDeath = 0 VsBreath = 2 VsMagic = 3 ) // RoomFlags are the room state bits (rogue.h room flags). type RoomFlags int16 // Room state bits (rogue.h ISDARK/ISGONE/ISMAZE). const ( Dark RoomFlags = 1 << iota // room is dark Gone // room is gone (a corridor) Maze // room is a maze ) // Has reports whether any of the given bits are set. func (f *RoomFlags) Has(b RoomFlags) bool { return *f&b != 0 } // Set turns the given bits on. func (f *RoomFlags) Set(b RoomFlags) { *f |= b } // Clear turns the given bits off. func (f *RoomFlags) Clear(b RoomFlags) { *f &^= b } // ObjFlags are the object state bits (rogue.h object flags). type ObjFlags int32 // Object state bits (rogue.h). const ( Cursed ObjFlags = 1 << iota // ISCURSED: object is cursed Known // ISKNOW: player knows details about the object Missile // ISMISL: object is a missile type Stackable // ISMANY: object comes in groups WasFound // ISFOUND (objects): object has been seen (ISFOUND shares the bit with creatures) Protected // ISPROT: armor is permanently protected ) // Has reports whether any of the given bits are set. func (f *ObjFlags) Has(b ObjFlags) bool { return *f&b != 0 } // Set turns the given bits on. func (f *ObjFlags) Set(b ObjFlags) { *f |= b } // Clear turns the given bits off. func (f *ObjFlags) Clear(b ObjFlags) { *f &^= b } // CreatureFlags are the creature state bits (rogue.h creature flags). The // C bit collisions are deliberate and preserved: one name of each pair // applies to monsters, the other to the hero, and they never coexist on // one creature. type CreatureFlags int32 // Creature state bits (rogue.h). const ( CanConfuse CreatureFlags = 0o000001 // CANHUH: creature can confuse CanSeeInvisible CreatureFlags = 0o000002 // CANSEE: creature can see invisible creatures Blind CreatureFlags = 0o000004 // ISBLIND: creature is blind Cancelled CreatureFlags = 0o000010 // ISCANC: creature has special qualities cancelled Levitating CreatureFlags = 0o000010 // ISLEVIT: hero is levitating Found CreatureFlags = 0o000020 // ISFOUND: creature has been seen Greedy CreatureFlags = 0o000040 // ISGREED: creature runs to protect gold Hasted CreatureFlags = 0o000100 // ISHASTE: creature has been hastened Targeted CreatureFlags = 0o000200 // ISTARGET: creature is the target of an 'f' command Held CreatureFlags = 0o000400 // ISHELD: creature has been held Confused CreatureFlags = 0o001000 // ISHUH: creature is confused Invisible CreatureFlags = 0o002000 // ISINVIS: creature is invisible Mean CreatureFlags = 0o004000 // ISMEAN: creature can wake when player enters room Hallucinating CreatureFlags = 0o004000 // ISHALU: hero is on acid trip Regenerates CreatureFlags = 0o010000 // ISREGEN: creature can regenerate Awake CreatureFlags = 0o020000 // ISRUN: creature is running at the player SenseMonsters CreatureFlags = 0o040000 // SEEMONST: hero can detect unseen monsters Flying CreatureFlags = 0o040000 // ISFLY: creature can fly Slowed CreatureFlags = 0o100000 // ISSLOW: creature has been slowed ) // Has reports whether any of the given bits are set. func (f *CreatureFlags) Has(b CreatureFlags) bool { return *f&b != 0 } // Set turns the given bits on. func (f *CreatureFlags) Set(b CreatureFlags) { *f |= b } // Clear turns the given bits off. func (f *CreatureFlags) Clear(b CreatureFlags) { *f &^= b } // PlaceFlags are the per-map-cell bits (rogue.h level map flags). The low // bits double as the passage number (FPassNum) or trap kind (FTrapMask). type PlaceFlags uint8 // Map cell bits (rogue.h). const ( FPassage PlaceFlags = 0x80 // F_PASS: is a passageway FSeen PlaceFlags = 0x40 // have seen this spot before FDropped PlaceFlags = 0x20 // object was dropped here FLocked PlaceFlags = 0x20 // door is locked FReal PlaceFlags = 0x10 // what you see is what you get FPassNum PlaceFlags = 0x0f // F_PNUM: passage number mask FTrapMask PlaceFlags = 0x07 // F_TMASK: trap number mask ) // Has reports whether any of the given bits are set. func (f *PlaceFlags) Has(b PlaceFlags) bool { return *f&b != 0 } // Set turns the given bits on. func (f *PlaceFlags) Set(b PlaceFlags) { *f |= b } // Clear turns the given bits off. func (f *PlaceFlags) Clear(b PlaceFlags) { *f &^= b } // TrapKind identifies a trap (rogue.h trap types). The kind is stored in // the low bits of a map cell's PlaceFlags (FTrapMask). type TrapKind int // Trap kinds (rogue.h T_* constants). const ( TrapDoor TrapKind = 0 TrapArrow TrapKind = 1 TrapSleep TrapKind = 2 TrapBear TrapKind = 3 TrapTeleport TrapKind = 4 TrapDart TrapKind = 5 TrapRust TrapKind = 6 TrapMystery TrapKind = 7 NumTrapTypes = 8 ) // PotionKind identifies a potion (rogue.h potion types). type PotionKind int // Potion kinds (rogue.h) const ( PotionConfusion PotionKind = iota PotionLSD PotionPoison PotionGainStrength PotionSeeInvisible PotionHealing PotionDetectMonsters PotionDetectMagic PotionRaiseLevel PotionExtraHealing PotionHaste PotionRestoreStrength PotionBlindness PotionLevitation NumPotionTypes ) // ScrollKind identifies a scroll (rogue.h scroll types). type ScrollKind int // Scroll kinds (rogue.h) const ( ScrollMonsterConfusion ScrollKind = iota ScrollMagicMapping ScrollHoldMonster ScrollSleep ScrollEnchantArmor ScrollIdentifyPotion ScrollIdentifyScroll ScrollIdentifyWeapon ScrollIdentifyArmor ScrollIdentifyRingOrStick ScrollScareMonster ScrollFoodDetection ScrollTeleportation ScrollEnchantWeapon ScrollCreateMonster ScrollRemoveCurse ScrollAggravateMonsters ScrollProtectArmor NumScrollTypes ) // WeaponKind identifies a weapon (rogue.h weapon types). type WeaponKind int // Weapon kinds (rogue.h) const ( WeaponMace WeaponKind = iota WeaponLongSword WeaponBow WeaponArrow WeaponDagger WeaponTwoHandedSword WeaponDart WeaponShuriken WeaponSpear WeaponFlame // fake entry for dragon breath (ick) ) // NumWeaponTypes counts the real weapons; the flame pseudo-weapon sits // just past them in the tables (C's MAXWEAPONS == FLAME). const NumWeaponTypes = WeaponFlame // ArmorKind identifies a suit of armor (rogue.h armor types). type ArmorKind int // Armor kinds (rogue.h) const ( ArmorLeather ArmorKind = iota ArmorRingMail ArmorStuddedLeather ArmorScaleMail ArmorChainMail ArmorSplintMail ArmorBandedMail ArmorPlateMail NumArmorTypes ) // RingKind identifies a ring (rogue.h ring types). type RingKind int // Ring kinds (rogue.h) const ( RingProtection RingKind = iota RingAddStrength RingSustainStrength RingSearching RingSeeInvisible RingAdornment RingAggravateMonsters RingDexterity RingIncreaseDamage RingRegeneration RingSlowDigestion RingTeleportation RingStealth RingMaintainArmor NumRingTypes ) // WandKind identifies a wand or staff (rogue.h rod/wand/staff types). type WandKind int // Wand kinds (rogue.h) const ( WandLight WandKind = iota WandInvisibility WandLightning WandFire WandCold WandPolymorph WandMagicMissile WandHasteMonster WandSlowMonster WandDrainLife WandNothing WandTeleportAway WandTeleportTo WandCancellation NumWandTypes ) // Coord is a position on the level (rogue.h coord). A value type: the C // ce(a,b) macro is plain == here. type Coord struct { X, Y int } // Stats describes a fighting being (rogue.h struct stats). type Stats struct { Str int // strength (s_str; 3..31) Exp int // experience Lvl int // level of mastery ArmorClass int // armor class (s_arm) HP int // hit points (s_hpt) Dmg DiceSpec // damage dice, e.g. "1x4/1x2" MaxHP int } // Room describes a room or passage network (rogue.h struct room). type Room struct { Pos Coord // upper left corner Max Coord // size of room Gold Coord // where the gold is GoldVal int // how much the gold is worth Flags RoomFlags Exits []Coord // where the exits are (r_exit[12]/r_nexits) } // MonsterKind is a bestiary entry (rogue.h struct monster). type MonsterKind struct { Name string // what to call the monster Carry int // probability of carrying something Flags CreatureFlags Stats Stats // initial stats } // ObjInfo describes one object class: its real name, generation // probability, score worth, and per-game identification state // (rogue.h struct obj_info). type ObjInfo struct { Name string Prob int Worth int Guess string Know bool } // Stone is a ring stone with its worth (rogue.h STONE). type Stone struct { Name string Value int } // CTRL maps a letter to its control character, as the C CTRL() macro. func CTRL(c byte) byte { return c & 0o37 } // distance returns the squared distance between two points (chase.c dist). func distance(y1, x1, y2, x2 int) int { dx := x2 - x1 dy := y2 - y1 return dx*dx + dy*dy } // distCp is dist_cp from chase.c. func distCp(c1, c2 Coord) int { return distance(c1.Y, c1.X, c2.Y, c2.X) } // sign is misc.c sign(): -1, 0 or 1. func sign(nm int) int { switch { case nm < 0: return -1 case nm > 0: return 1 } return 0 }