Ejemplo n.º 1
0
        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);
            }
        }
Ejemplo n.º 2
0
        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;
                }
            }
        }
Ejemplo n.º 3
0
        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);
                }
            }
        }
Ejemplo n.º 4
0
        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);
            }
        }