package game // ItemLore is the per-game item identity state: the randomized appearance // names and the seven mutable ObjInfo tables (extern.c/init.c). type ItemLore struct { PotColors [MaxPotions]string // p_colors: colors of the potions ScrNames [MaxScrolls]string // s_names: names of the scrolls RingStones [MaxRings]string // r_stones: stone settings of the rings WandMade [MaxSticks]string // ws_made: what sticks are made of WandType [MaxSticks]string // ws_type: "wand" or "staff" Things [NumThings]ObjInfo Potions [MaxPotions]ObjInfo Scrolls [MaxScrolls]ObjInfo Rings [MaxRings]ObjInfo Sticks [MaxSticks]ObjInfo Weapons [MaxWeapons + 1]ObjInfo Armors [MaxArmors]ObjInfo Group int // group number for the next stack of missiles (weapons.c `group`) } // Options are the user-settable game options (options.c optlist). type Options struct { Terse bool // terse: shorter messages FightFlush bool // flush: flush typeahead during battle Jump bool // jump: show position only at end of run SeeFloor bool // seefloor: show the lamp-illuminated floor PassGo bool // passgo: follow turnings in passageways Tombstone bool // tombstone: print tombstone when killed InvType int // inven: inventory style (InvOver/InvSlow/InvClear) } // Config carries everything needed to construct a game. type Config struct { Seed int32 // dungeon number; the caller derives it (time+pid or SEED env) Name string // player name (overridden by ROGUEOPTS name=) RogueOpts string // the ROGUEOPTS environment string Home string // home directory (save file default location) ScorePath string // scoreboard file; empty disables scoring Wizard bool // enable debug commands (implies NoScore) Term Terminal // the display/input device; nil runs headless } // RogueGame is one complete game of Rogue: every piece of state that was a // global (or file-scope static) in the C sources, plus the terminal it is // played on. Construct with NewGame, then call Run. // // The struct grows with the port; fields appear in the phase that ports the // code owning them. type RogueGame struct { // identity / RNG Rng *Rng Dnum int // dungeon number Whoami string // name of player Fruit string // favorite fruit Home string // user's home directory FileName string // save file name Wizard bool // true if allows wizard commands NoScore bool // was a wizard sometime // the world Player Player Level Level Depth int // C `level`: what level she is on MaxDepth int // C `max_level`: deepest player has gone HasAmulet bool // C `amulet`: he found the amulet SeenStairs bool // have seen the stairs (for lsd) // turn/command engine Playing bool // true until he quits After bool // true if we want after daemons Again bool // repeating the last command Count int // number of times to repeat command NoCommand int // number of turns asleep NoMove int // number of turns held in place Quiet int // number of quiet turns Running bool // true if player is running RunCh byte // direction player is running DoorStop bool // stop running when we pass a door Firstmove bool // first move after setting door_stop MoveOn bool // next move shouldn't pick up items ToDeath bool // fighting is to the death! Kamikaze bool // to_death really to DEATH HasHit bool // has a "hit" message pending in msg MaxHit int // max damage done to her in to_death Take byte // thing she is taking Delta Coord DirCh byte LastComm byte LastDir byte LLastComm byte LLastDir byte LastPick *Object LLastPick *Object lastDelt Coord // misc.c get_dir static last_delt // dungeon generation working state maze mazeState // rooms.c maze statics pnum int // passages.c passnum statics newpnum bool // daemons/fuses Daemons DaemonList // screen / messages scr *Screen Msgs MsgLine statusCache statusCache invPage invPage // things.c discovery-list pagination statics // UI state StatMsg bool // should status() print as a msg() InvDescribe bool // say which way items are being used QComm bool // are we executing a 'Q' command? InShell bool // true if executing a shell Oldpos Coord // position before last look() call Oldrp *Room NObjs int // # items listed in inventory() call // options and item identity Options Options Items ItemLore // scores LastScore int AllScore bool ScorePath string } // NewGame builds a game from cfg, seeds the RNG, and randomizes the item // appearance tables (the front half of main.c main(); the player roll-up // and first level arrive with later porting phases). func NewGame(cfg Config) *RogueGame { g := &RogueGame{ Rng: &Rng{Seed: cfg.Seed}, Dnum: int(cfg.Seed), Whoami: cfg.Name, Fruit: "slime-mold", Home: cfg.Home, Wizard: cfg.Wizard, NoScore: cfg.Wizard, Playing: true, Depth: 1, ScorePath: cfg.ScorePath, LastScore: -1, } g.Options = Options{ SeeFloor: true, Tombstone: true, InvType: InvOver, } g.InvDescribe = true g.Msgs.SaveMsg = true g.scr = NewScreen(cfg.Term) g.FileName = cfg.Home + "/rogue.save" if cfg.Wizard { g.Player.Flags.Set(SeeMonst) } // TODO(port): parse cfg.RogueOpts once options.go lands. g.Items.Group = 2 // weapons.c: int group = 2 for i := range g.Level.Passages { g.Level.Passages[i].Flags = IsGone | IsDark } g.initProbs() // set up prob tables for objects g.initPlayer() // set up initial player stats g.initNames() // set up names of scrolls g.initColors() // set up colors of potions g.initStones() // set up stone settings of rings g.initMaterials() // set up materials of wands return g } // quit has the player make certain, then exits (main.c quit). The final // scoring display arrives with the endgame phase. func (g *RogueGame) quit(int) { // Reset the message position in case we got here via an interrupt if !g.QComm { g.Msgs.Mpos = 0 } oy, ox := g.scr.Std.GetYX() g.msg("really quit?") if g.readchar() == 'y' { g.clear() g.scr.Std.MvPrintw(NumLines-2, 0, "You quit with %d gold pieces", g.Player.Purse) g.move(NumLines-1, 0) g.refresh() // TODO(port): score(purse, 1, 0) once rip.go lands. g.gameOver() return } g.move(0, 0) g.clrtoeol() g.status() g.move(oy, ox) g.refresh() g.Msgs.Mpos = 0 g.Count = 0 g.ToDeath = false } // gameOver ends the game loop; it replaces the C exit() calls so that Run // can unwind normally and restore the terminal. func (g *RogueGame) gameOver() { g.Playing = false }