private static void InitializePlayer() { bool newGame = true; // If this is your first readthrough of the source, I recommend checking out the documentation for Loaf.Config and Loaf.Cns.Choice at this time. if (File.Exists(Config.Global.saveFilename)) { var choice = Cns.Choice <StartGameChoiceDec>(); if (choice == StartGameChoices.Load) { newGame = false; // Check out Player.Record() for the implementation of Player deserialization. Player.Set(Dec.Recorder.Read <Player>(File.ReadAllText(Config.Global.saveFilename))); } Cns.Out(""); Cns.Out(""); } // Create player according to our global config. if (newGame) { var player = new Player(); foreach (var item in Config.Global.startingItems) { player.AcquireItem(item); } Player.Set(player); } }
public static void Run() { InitializePlayer(); Cns.Out("Welcome to Legend of the Amethyst Futon!"); Cns.Out("Your quest: find the Amethyst Futon, rumored to be the most comfortable resting device in the kingdom."); Cns.Out("Good luck!"); while (true) { Cns.Out(""); Cns.Out(""); Cns.Out("You stand at a crossroads, both literally and metaphorically."); Cns.Out(""); // This is a good example of traversing an entire database for objects. // There's no function that returns the LocationDecs we should be using, nor is there a place where we enumerate them explicitly. // Instead, we just grab *all* the Locations, verify which ones are available, and then show those. // If someone wanted to make a game mod to introduce a new Location, all they'd need would be a new LocationDec and its associated code or data. // If you needed more complicated (and moddable) Location accessibility, it'd be reasonable to just make it a virtual function on LocationDec. var destinations = Dec.Database <LocationDec> .List.Where(loc => loc.requiredItem == null || Player.Instance.Inventory.Contains(loc.requiredItem)); var location = Cns.Choice(items: destinations.ToArray(), longForm: true).Create(); var result = location.Visit(); if (result == Location.Outcomes.Death) { Cns.Out(""); Cns.Out("You have died.", color: System.ConsoleColor.Red); Cns.Out("But that's okay. You got better."); } else if (result == Location.Outcomes.Victory) { Cns.Out(""); Cns.Out("CONGRATULATIONS! You win!"); // Unceremoniously dump the player out of the game. return; } } }
public override Location.OutcomeDec Visit() { while (true) { var result = Fight(dec.monsters.Roll()); if (result == Outcomes.Death) { return(Location.Outcomes.Death); } else if (result == Outcomes.Fled) { Cns.Out("You escape the dungeon."); return(Location.Outcomes.Return); } var choice = Cns.Choice <DungeonChoiceDec>(); if (choice == DungeonChoices.Leave) { return(Location.Outcomes.Return); } } }
private static OutcomeDec Fight(MonsterDec monster) { int playerHp = Config.Global.playerHp; int monsterHp = monster.hp; Cns.Out($""); Cns.Out($"A {monster.name} approaches!"); while (playerHp > 0 && monsterHp > 0) { Cns.Out($""); Cns.Out($""); Cns.Out($"{playerHp,4} / {Config.Global.playerHp,4}: Your health"); Cns.Out($"{monsterHp,4} / {monster.hp,4}: The monster's health"); Cns.Out($""); var choice = Cns.Choice <FightChoiceDec>(); if (choice == DungeonChoices.Fight) { int attack = monster.damage.Roll(); int defense = Player.Instance.Inventory.OfType <ArmorDec>().Select(armor => armor.armor.Roll()).Sum(); if (attack > defense) { // Okay this is actually a bug - this should be playerHp -= (attack - defense). // Except I already went through and (vaguely) balanced the game, and this isn't meant to be *fun*, just a tech demo. // So I'm just leaving it in place. playerHp -= monster.damage.Roll(); } else { Cns.Out("Its attack bounces off your armor!"); } monsterHp -= Player.Instance.CurrentWeapon.damage.Roll(); } else if (choice == DungeonChoices.Run) { return(Outcomes.Fled); } } if (monsterHp > 0) { return(Outcomes.Death); } else { Cns.Out(""); Cns.Out("The monster is slain!", color: System.ConsoleColor.White); if (monster.loot != null && !Player.Instance.Inventory.Contains(monster.loot)) { Cns.Out($"You find a {monster.loot.name}!", color: System.ConsoleColor.Cyan); // You could also make this a virtual function on ItemDec with an override on ArmorDec, maybe named OnPickup(). if (monster.loot is ArmorDec) { Cns.Out($"You put it on. It fits perfectly.", color: System.ConsoleColor.Cyan); } Player.Instance.AcquireItem(monster.loot); } int goldIncome = monster.gold.Roll(); Player.Instance.AcquireGold(goldIncome); Cns.Out($"You root around in the dirt for a bit and find {goldIncome} gold."); Cns.Out(""); return(Outcomes.Victory); } }