Skip to content

Instantly share code, notes, and snippets.

@ScottLilly
Created November 29, 2016 23:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ScottLilly/56365e8c1eabfb907ba6f384a9cbace2 to your computer and use it in GitHub Desktop.
Save ScottLilly/56365e8c1eabfb907ba6f384a9cbace2 to your computer and use it in GitHub Desktop.
Lesson 25.1 - Select a random monster at a location
using System.Collections.Generic;
using System.Linq;
namespace Engine
{
public class Location
{
private readonly SortedList<int, int> _monstersAtLocation = new SortedList<int, int>();
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public Item ItemRequiredToEnter { get; set; }
public Quest QuestAvailableHere { get; set; }
public Vendor VendorWorkingHere { get; set; }
public Location LocationToNorth { get; set; }
public Location LocationToEast { get; set; }
public Location LocationToSouth { get; set; }
public Location LocationToWest { get; set; }
public bool HasAMonster { get { return _monstersAtLocation.Count > 0; } }
public bool HasAQuest { get { return QuestAvailableHere != null; } }
public bool DoesNotHaveAnItemRequiredToEnter { get { return ItemRequiredToEnter == null; } }
public Location(int id, string name, string description,
Item itemRequiredToEnter = null, Quest questAvailableHere = null)
{
ID = id;
Name = name;
Description = description;
ItemRequiredToEnter = itemRequiredToEnter;
QuestAvailableHere = questAvailableHere;
}
public void AddMonster(int monsterID, int percentageOfAppearance)
{
if(_monstersAtLocation.ContainsKey(monsterID))
{
_monstersAtLocation[monsterID] = percentageOfAppearance;
}
else
{
_monstersAtLocation.Add(monsterID, percentageOfAppearance);
}
}
public Monster NewInstanceOfMonsterLivingHere()
{
if(!HasAMonster)
{
return null;
}
// Total the percentages of all monsters at this location.
int totalPercentages = _monstersAtLocation.Values.Sum();
// Select a random number between 1 and the total (in case the total of percentages is not 100).
int randomNumber = RandomNumberGenerator.NumberBetween(1, totalPercentages);
// Loop through the monster list,
// adding the monster's percentage chance of appearing to the runningTotal variable.
// When the random number is lower than the runningTotal,
// that is the monster to return.
int runningTotal = 0;
foreach(KeyValuePair<int, int> monsterKeyValuePair in _monstersAtLocation)
{
runningTotal += monsterKeyValuePair.Value;
if(randomNumber <= runningTotal)
{
return World.MonsterByID(monsterKeyValuePair.Key).NewInstanceOfMonster();
}
}
// In case there was a problem, return the last monster in the list.
return World.MonsterByID(_monstersAtLocation.Keys.Last()).NewInstanceOfMonster();
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Xml;
namespace Engine
{
public class Player : LivingCreature
{
private int _gold;
private int _experiencePoints;
private Location _currentLocation;
public event EventHandler<MessageEventArgs> OnMessage;
public int Gold
{
get { return _gold; }
set
{
_gold = value;
OnPropertyChanged("Gold");
}
}
public int ExperiencePoints
{
get { return _experiencePoints; }
private set
{
_experiencePoints = value;
OnPropertyChanged("ExperiencePoints");
OnPropertyChanged("Level");
}
}
public int Level
{
get { return ((ExperiencePoints / 100) + 1); }
}
public Location CurrentLocation
{
get { return _currentLocation; }
set
{
_currentLocation = value;
OnPropertyChanged("CurrentLocation");
}
}
public Weapon CurrentWeapon { get; set; }
public BindingList<InventoryItem> Inventory { get; set; }
public List<Weapon> Weapons
{
get { return Inventory.Where(x => x.Details is Weapon).Select(x => x.Details as Weapon).ToList(); }
}
public List<HealingPotion> Potions
{
get { return Inventory.Where(x => x.Details is HealingPotion).Select(x => x.Details as HealingPotion).ToList(); }
}
public BindingList<PlayerQuest> Quests { get; set; }
private Monster CurrentMonster { get; set; }
private Player(int currentHitPoints, int maximumHitPoints, int gold, int experiencePoints) : base(currentHitPoints, maximumHitPoints)
{
Gold = gold;
ExperiencePoints = experiencePoints;
Inventory = new BindingList<InventoryItem>();
Quests = new BindingList<PlayerQuest>();
}
public static Player CreateDefaultPlayer()
{
Player player = new Player(10, 10, 20, 0);
player.Inventory.Add(new InventoryItem(World.ItemByID(World.ITEM_ID_RUSTY_SWORD), 1));
player.CurrentLocation = World.LocationByID(World.LOCATION_ID_HOME);
return player;
}
public static Player CreatePlayerFromXmlString(string xmlPlayerData)
{
try
{
XmlDocument playerData = new XmlDocument();
playerData.LoadXml(xmlPlayerData);
int currentHitPoints = Convert.ToInt32(playerData.SelectSingleNode("/Player/Stats/CurrentHitPoints").InnerText);
int maximumHitPoints = Convert.ToInt32(playerData.SelectSingleNode("/Player/Stats/MaximumHitPoints").InnerText);
int gold = Convert.ToInt32(playerData.SelectSingleNode("/Player/Stats/Gold").InnerText);
int experiencePoints = Convert.ToInt32(playerData.SelectSingleNode("/Player/Stats/ExperiencePoints").InnerText);
Player player = new Player(currentHitPoints, maximumHitPoints, gold, experiencePoints);
int currentLocationID = Convert.ToInt32(playerData.SelectSingleNode("/Player/Stats/CurrentLocation").InnerText);
player.CurrentLocation = World.LocationByID(currentLocationID);
if(playerData.SelectSingleNode("/Player/Stats/CurrentWeapon") != null)
{
int currentWeaponID = Convert.ToInt32(playerData.SelectSingleNode("/Player/Stats/CurrentWeapon").InnerText);
player.CurrentWeapon = (Weapon)World.ItemByID(currentWeaponID);
}
foreach(XmlNode node in playerData.SelectNodes("/Player/InventoryItems/InventoryItem"))
{
int id = Convert.ToInt32(node.Attributes["ID"].Value);
int quantity = Convert.ToInt32(node.Attributes["Quantity"].Value);
for(int i = 0; i < quantity; i++)
{
player.AddItemToInventory(World.ItemByID(id));
}
}
foreach(XmlNode node in playerData.SelectNodes("/Player/PlayerQuests/PlayerQuest"))
{
int id = Convert.ToInt32(node.Attributes["ID"].Value);
bool isCompleted = Convert.ToBoolean(node.Attributes["IsCompleted"].Value);
PlayerQuest playerQuest = new PlayerQuest(World.QuestByID(id));
playerQuest.IsCompleted = isCompleted;
player.Quests.Add(playerQuest);
}
return player;
}
catch
{
// If there was an error with the XML data, return a default player object
return CreateDefaultPlayer();
}
}
public static Player CreatePlayerFromDatabase(int currentHitPoints, int maximumHitPoints, int gold, int experiencePoints, int currentLocationID)
{
Player player = new Player(currentHitPoints, maximumHitPoints, gold, experiencePoints);
player.MoveTo(World.LocationByID(currentLocationID));
return player;
}
public void MoveTo(Location location)
{
if(PlayerDoesNotHaveTheRequiredItemToEnter(location))
{
RaiseMessage("You must have a " + location.ItemRequiredToEnter.Name + " to enter this location.");
return;
}
// The player can enter this location
CurrentLocation = location;
CompletelyHeal();
if(location.HasAQuest)
{
if(PlayerDoesNotHaveThisQuest(location.QuestAvailableHere))
{
GiveQuestToPlayer(location.QuestAvailableHere);
}
else
{
if(PlayerHasNotCompleted(location.QuestAvailableHere) &&
PlayerHasAllQuestCompletionItemsFor(location.QuestAvailableHere))
{
GivePlayerQuestRewards(location.QuestAvailableHere);
}
}
}
SetTheCurrentMonsterForTheCurrentLocation(location);
}
public void MoveNorth()
{
if(CurrentLocation.LocationToNorth != null)
{
MoveTo(CurrentLocation.LocationToNorth);
}
}
public void MoveEast()
{
if(CurrentLocation.LocationToEast != null)
{
MoveTo(CurrentLocation.LocationToEast);
}
}
public void MoveSouth()
{
if(CurrentLocation.LocationToSouth != null)
{
MoveTo(CurrentLocation.LocationToSouth);
}
}
public void MoveWest()
{
if(CurrentLocation.LocationToWest != null)
{
MoveTo(CurrentLocation.LocationToWest);
}
}
public void UseWeapon(Weapon weapon)
{
int damage = RandomNumberGenerator.NumberBetween(weapon.MinimumDamage, weapon.MaximumDamage);
if(damage == 0)
{
RaiseMessage("You missed the " + CurrentMonster.Name);
}
else
{
CurrentMonster.CurrentHitPoints -= damage;
RaiseMessage("You hit the " + CurrentMonster.Name + " for " + damage + " points.");
}
if(CurrentMonster.IsDead)
{
LootTheCurrentMonster();
// "Move" to the current location, to refresh the current monster
MoveTo(CurrentLocation);
}
else
{
LetTheMonsterAttack();
}
}
private void LootTheCurrentMonster()
{
RaiseMessage("");
RaiseMessage("You defeated the " + CurrentMonster.Name);
RaiseMessage("You receive " + CurrentMonster.RewardExperiencePoints + " experience points");
RaiseMessage("You receive " + CurrentMonster.RewardGold + " gold");
AddExperiencePoints(CurrentMonster.RewardExperiencePoints);
Gold += CurrentMonster.RewardGold;
// Give monster's loot items to the player
foreach(InventoryItem inventoryItem in CurrentMonster.LootItems)
{
AddItemToInventory(inventoryItem.Details);
RaiseMessage(string.Format("You loot {0} {1}", inventoryItem.Quantity, inventoryItem.Description));
}
RaiseMessage("");
}
public void UsePotion(HealingPotion potion)
{
RaiseMessage("You drink a " + potion.Name);
HealPlayer(potion.AmountToHeal);
RemoveItemFromInventory(potion);
// The player used their turn to drink the potion, so let the monster attack now
LetTheMonsterAttack();
}
public void AddItemToInventory(Item itemToAdd, int quantity = 1)
{
InventoryItem existingItemInInventory = Inventory.SingleOrDefault(ii => ii.Details.ID == itemToAdd.ID);
if(existingItemInInventory == null)
{
Inventory.Add(new InventoryItem(itemToAdd, quantity));
}
else
{
existingItemInInventory.Quantity += quantity;
}
RaiseInventoryChangedEvent(itemToAdd);
}
public void RemoveItemFromInventory(Item itemToRemove, int quantity = 1)
{
InventoryItem item = Inventory.SingleOrDefault(ii => ii.Details.ID == itemToRemove.ID && ii.Quantity >= quantity);
if(item != null)
{
item.Quantity -= quantity;
if(item.Quantity == 0)
{
Inventory.Remove(item);
}
RaiseInventoryChangedEvent(itemToRemove);
}
}
public string ToXmlString()
{
XmlDocument playerData = new XmlDocument();
// Create the top-level XML node
XmlNode player = playerData.CreateElement("Player");
playerData.AppendChild(player);
// Create the "Stats" child node to hold the other player statistics nodes
XmlNode stats = playerData.CreateElement("Stats");
player.AppendChild(stats);
// Create the child nodes for the "Stats" node
CreateNewChildXmlNode(playerData, stats, "CurrentHitPoints", CurrentHitPoints);
CreateNewChildXmlNode(playerData, stats, "MaximumHitPoints", MaximumHitPoints);
CreateNewChildXmlNode(playerData, stats, "Gold", Gold);
CreateNewChildXmlNode(playerData, stats, "ExperiencePoints", ExperiencePoints);
CreateNewChildXmlNode(playerData, stats, "CurrentLocation", CurrentLocation.ID);
if(CurrentWeapon != null)
{
CreateNewChildXmlNode(playerData, stats, "CurrentWeapon", CurrentWeapon.ID);
}
// Create the "InventoryItems" child node to hold each InventoryItem node
XmlNode inventoryItems = playerData.CreateElement("InventoryItems");
player.AppendChild(inventoryItems);
// Create an "InventoryItem" node for each item in the player's inventory
foreach(InventoryItem item in Inventory)
{
XmlNode inventoryItem = playerData.CreateElement("InventoryItem");
AddXmlAttributeToNode(playerData, inventoryItem, "ID", item.Details.ID);
AddXmlAttributeToNode(playerData, inventoryItem, "Quantity", item.Quantity);
inventoryItems.AppendChild(inventoryItem);
}
// Create the "PlayerQuests" child node to hold each PlayerQuest node
XmlNode playerQuests = playerData.CreateElement("PlayerQuests");
player.AppendChild(playerQuests);
// Create a "PlayerQuest" node for each quest the player has acquired
foreach(PlayerQuest quest in Quests)
{
XmlNode playerQuest = playerData.CreateElement("PlayerQuest");
AddXmlAttributeToNode(playerData, playerQuest, "ID", quest.Details.ID);
AddXmlAttributeToNode(playerData, playerQuest, "IsCompleted", quest.IsCompleted);
playerQuests.AppendChild(playerQuest);
}
return playerData.InnerXml; // The XML document, as a string, so we can save the data to disk
}
private bool HasRequiredItemToEnterThisLocation(Location location)
{
if(location.DoesNotHaveAnItemRequiredToEnter)
{
return true;
}
// See if the player has the required item in their inventory
return Inventory.Any(ii => ii.Details.ID == location.ItemRequiredToEnter.ID);
}
private void SetTheCurrentMonsterForTheCurrentLocation(Location location)
{
// Populate the current monster with this location's monster (or null, if there is no monster here)
CurrentMonster = location.NewInstanceOfMonsterLivingHere();
if(CurrentMonster != null)
{
RaiseMessage("You see a " + CurrentMonster.Name);
}
}
private bool PlayerDoesNotHaveTheRequiredItemToEnter(Location location)
{
return !HasRequiredItemToEnterThisLocation(location);
}
private bool PlayerDoesNotHaveThisQuest(Quest quest)
{
return Quests.All(pq => pq.Details.ID != quest.ID);
}
private bool PlayerHasNotCompleted(Quest quest)
{
return Quests.Any(pq => pq.Details.ID == quest.ID && !pq.IsCompleted);
}
private void GiveQuestToPlayer(Quest quest)
{
RaiseMessage("You receive the " + quest.Name + " quest.");
RaiseMessage(quest.Description);
RaiseMessage("To complete it, return with:");
foreach(QuestCompletionItem qci in quest.QuestCompletionItems)
{
RaiseMessage(string.Format("{0} {1}", qci.Quantity,
qci.Quantity == 1 ? qci.Details.Name : qci.Details.NamePlural));
}
RaiseMessage("");
Quests.Add(new PlayerQuest(quest));
}
private bool PlayerHasAllQuestCompletionItemsFor(Quest quest)
{
// See if the player has all the items needed to complete the quest here
foreach(QuestCompletionItem qci in quest.QuestCompletionItems)
{
// Check each item in the player's inventory, to see if they have it, and enough of it
if(!Inventory.Any(ii => ii.Details.ID == qci.Details.ID && ii.Quantity >= qci.Quantity))
{
return false;
}
}
// If we got here, then the player must have all the required items, and enough of them, to complete the quest.
return true;
}
private void RemoveQuestCompletionItems(Quest quest)
{
foreach(QuestCompletionItem qci in quest.QuestCompletionItems)
{
InventoryItem item = Inventory.SingleOrDefault(ii => ii.Details.ID == qci.Details.ID);
if(item != null)
{
RemoveItemFromInventory(item.Details, qci.Quantity);
}
}
}
private void AddExperiencePoints(int experiencePointsToAdd)
{
ExperiencePoints += experiencePointsToAdd;
MaximumHitPoints = (Level * 10);
}
private void GivePlayerQuestRewards(Quest quest)
{
RaiseMessage("");
RaiseMessage("You complete the '" + quest.Name + "' quest.");
RaiseMessage("You receive: ");
RaiseMessage(quest.RewardExperiencePoints + " experience points");
RaiseMessage(quest.RewardGold + " gold");
RaiseMessage(quest.RewardItem.Name, true);
AddExperiencePoints(quest.RewardExperiencePoints);
Gold += quest.RewardGold;
RemoveQuestCompletionItems(quest);
AddItemToInventory(quest.RewardItem);
MarkPlayerQuestCompleted(quest);
}
private void MarkPlayerQuestCompleted(Quest quest)
{
PlayerQuest playerQuest = Quests.SingleOrDefault(pq => pq.Details.ID == quest.ID);
if(playerQuest != null)
{
playerQuest.IsCompleted = true;
}
}
private void LetTheMonsterAttack()
{
int damageToPlayer = RandomNumberGenerator.NumberBetween(0, CurrentMonster.MaximumDamage);
RaiseMessage("The " + CurrentMonster.Name + " did " + damageToPlayer + " points of damage.");
CurrentHitPoints -= damageToPlayer;
if(IsDead)
{
RaiseMessage("The " + CurrentMonster.Name + " killed you.");
MoveHome();
}
}
private void HealPlayer(int hitPointsToHeal)
{
CurrentHitPoints = Math.Min(CurrentHitPoints + hitPointsToHeal, MaximumHitPoints);
}
private void CompletelyHeal()
{
CurrentHitPoints = MaximumHitPoints;
}
private void MoveHome()
{
MoveTo(World.LocationByID(World.LOCATION_ID_HOME));
}
private void CreateNewChildXmlNode(XmlDocument document, XmlNode parentNode, string elementName, object value)
{
XmlNode node = document.CreateElement(elementName);
node.AppendChild(document.CreateTextNode(value.ToString()));
parentNode.AppendChild(node);
}
private void AddXmlAttributeToNode(XmlDocument document, XmlNode node, string attributeName, object value)
{
XmlAttribute attribute = document.CreateAttribute(attributeName);
attribute.Value = value.ToString();
node.Attributes.Append(attribute);
}
private void RaiseInventoryChangedEvent(Item item)
{
if(item is Weapon)
{
OnPropertyChanged("Weapons");
}
if(item is HealingPotion)
{
OnPropertyChanged("Potions");
}
}
private void RaiseMessage(string message, bool addExtraNewLine = false)
{
if(OnMessage != null)
{
OnMessage(this, new MessageEventArgs(message, addExtraNewLine));
}
}
}
}
using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using Engine;
namespace SuperAdventureConsole
{
public class Program
{
private const string PLAYER_DATA_FILE_NAME = "PlayerData.xml";
private static Player _player;
private static void Main(string[] args)
{
// Load the player
LoadGameData();
Console.WriteLine("Type 'Help' to see a list of commands");
Console.WriteLine("");
DisplayCurrentLocation();
// Connect player events to functions that will display in the UI
_player.PropertyChanged += Player_OnPropertyChanged;
_player.OnMessage += Player_OnMessage;
// Infinite loop, until the user types "exit"
while(true)
{
// Display a prompt, so the user knows to type something
Console.Write(">");
// Wait for the user to type something, and press the <Enter> key
string userInput = Console.ReadLine();
// If they typed a blank line, loop back and wait for input again
if(userInput == null)
{
continue;
}
// Convert to lower-case, to make comparisons easier
string cleanedInput = userInput.ToLower();
// Save the current game data, and break out of the "while(true)" loop
if(cleanedInput == "exit")
{
SaveGameData();
break;
}
// If the user typed something, try to determine what to do
ParseInput(cleanedInput);
}
}
private static void Player_OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(e.PropertyName == "CurrentLocation")
{
DisplayCurrentLocation();
if(_player.CurrentLocation.VendorWorkingHere != null)
{
Console.WriteLine("You see a vendor here: {0}", _player.CurrentLocation.VendorWorkingHere.Name);
}
}
}
private static void Player_OnMessage(object sender, MessageEventArgs e)
{
Console.WriteLine(e.Message);
if(e.AddExtraNewLine)
{
Console.WriteLine("");
}
}
private static void ParseInput(string input)
{
if(input.Contains("help") || input == "?")
{
DisplayHelpText();
}
else if(input == "stats")
{
DisplayPlayerStats();
}
else if(input == "look")
{
DisplayCurrentLocation();
}
else if(input.Contains("north"))
{
if(_player.CurrentLocation.LocationToNorth == null)
{
Console.WriteLine("You cannot move North");
}
else
{
_player.MoveNorth();
}
}
else if(input.Contains("east"))
{
if(_player.CurrentLocation.LocationToEast == null)
{
Console.WriteLine("You cannot move East");
}
else
{
_player.MoveEast();
}
}
else if(input.Contains("south"))
{
if(_player.CurrentLocation.LocationToSouth == null)
{
Console.WriteLine("You cannot move South");
}
else
{
_player.MoveSouth();
}
}
else if(input.Contains("west"))
{
if(_player.CurrentLocation.LocationToWest == null)
{
Console.WriteLine("You cannot move West");
}
else
{
_player.MoveWest();
}
}
else if(input == "inventory")
{
foreach(InventoryItem inventoryItem in _player.Inventory)
{
Console.WriteLine("{0}: {1}", inventoryItem.Description, inventoryItem.Quantity);
}
}
else if(input == "quests")
{
if(_player.Quests.Count == 0)
{
Console.WriteLine("You do not have any quests");
}
else
{
foreach(PlayerQuest playerQuest in _player.Quests)
{
Console.WriteLine("{0}: {1}", playerQuest.Name,
playerQuest.IsCompleted ? "Completed" : "Incomplete");
}
}
}
else if(input.Contains("attack"))
{
AttackMonster();
}
else if(input.StartsWith("equip "))
{
EquipWeapon(input);
}
else if(input.StartsWith("drink "))
{
DrinkPotion(input);
}
else if(input == "trade")
{
ViewTradeInventory();
}
else if(input.StartsWith("buy "))
{
BuyItem(input);
}
else if(input.StartsWith("sell "))
{
SellItem(input);
}
else
{
Console.WriteLine("I do not understand");
Console.WriteLine("Type 'Help' to see a list of available commands");
}
// Write a blank line, to keep the UI a little cleaner
Console.WriteLine("");
}
private static void DisplayHelpText()
{
Console.WriteLine("Available commands");
Console.WriteLine("====================================");
Console.WriteLine("Stats - Display player information");
Console.WriteLine("Look - Get the description of your location");
Console.WriteLine("Inventory - Display your inventory");
Console.WriteLine("Quests - Display your quests");
Console.WriteLine("Attack - Fight the monster");
Console.WriteLine("Equip <weapon name> - Set your current weapon");
Console.WriteLine("Drink <potion name> - Drink a potion");
Console.WriteLine("Trade - display your inventory and vendor's inventory");
Console.WriteLine("Buy <item name> - Buy an item from a vendor");
Console.WriteLine("Sell <item name> - Sell an item to a vendor");
Console.WriteLine("North - Move North");
Console.WriteLine("South - Move South");
Console.WriteLine("East - Move East");
Console.WriteLine("West - Move West");
Console.WriteLine("Exit - Save the game and exit");
}
private static void DisplayPlayerStats()
{
Console.WriteLine("Current hit points: {0}", _player.CurrentHitPoints);
Console.WriteLine("Maximum hit points: {0}", _player.MaximumHitPoints);
Console.WriteLine("Experience Points: {0}", _player.ExperiencePoints);
Console.WriteLine("Level: {0}", _player.Level);
Console.WriteLine("Gold: {0}", _player.Gold);
}
private static void AttackMonster()
{
if(!_player.CurrentLocation.HasAMonster)
{
Console.WriteLine("There is nothing here to attack");
}
else
{
if(_player.CurrentWeapon == null)
{
// Select the first weapon in the player's inventory
// (or 'null', if they do not have any weapons)
_player.CurrentWeapon = _player.Weapons.FirstOrDefault();
}
if(_player.CurrentWeapon == null)
{
Console.WriteLine("You do not have any weapons");
}
else
{
_player.UseWeapon(_player.CurrentWeapon);
}
}
}
private static void EquipWeapon(string input)
{
string inputWeaponName = input.Substring(6).Trim();
if(string.IsNullOrEmpty(inputWeaponName))
{
Console.WriteLine("You must enter the name of the weapon to equip");
}
else
{
Weapon weaponToEquip =
_player.Weapons.SingleOrDefault(
x => x.Name.ToLower() == inputWeaponName || x.NamePlural.ToLower() == inputWeaponName);
if(weaponToEquip == null)
{
Console.WriteLine("You do not have the weapon: {0}", inputWeaponName);
}
else
{
_player.CurrentWeapon = weaponToEquip;
Console.WriteLine("You equip your {0}", _player.CurrentWeapon.Name);
}
}
}
private static void DrinkPotion(string input)
{
string inputPotionName = input.Substring(6).Trim();
if(string.IsNullOrEmpty(inputPotionName))
{
Console.WriteLine("You must enter the name of the potion to drink");
}
else
{
HealingPotion potionToDrink =
_player.Potions.SingleOrDefault(
x => x.Name.ToLower() == inputPotionName || x.NamePlural.ToLower() == inputPotionName);
if(potionToDrink == null)
{
Console.WriteLine("You do not have the potion: {0}", inputPotionName);
}
else
{
_player.UsePotion(potionToDrink);
}
}
}
private static void ViewTradeInventory()
{
if(LocationDoesNotHaveVendor())
{
return;
}
Console.WriteLine("PLAYER INVENTORY");
Console.WriteLine("================");
if(_player.Inventory.Count(x => x.Price != World.UNSELLABLE_ITEM_PRICE) == 0)
{
Console.WriteLine("You do not have any inventory");
}
else
{
foreach(
InventoryItem inventoryItem in _player.Inventory.Where(x => x.Price != World.UNSELLABLE_ITEM_PRICE))
{
Console.WriteLine("{0} {1} Price: {2}", inventoryItem.Quantity, inventoryItem.Description,
inventoryItem.Price);
}
}
Console.WriteLine("");
Console.WriteLine("VENDOR INVENTORY");
Console.WriteLine("================");
if(_player.CurrentLocation.VendorWorkingHere.Inventory.Count == 0)
{
Console.WriteLine("The vendor does not have any inventory");
}
else
{
foreach(InventoryItem inventoryItem in _player.CurrentLocation.VendorWorkingHere.Inventory)
{
Console.WriteLine("{0} {1} Price: {2}", inventoryItem.Quantity, inventoryItem.Description,
inventoryItem.Price);
}
}
}
private static void BuyItem(string input)
{
if(LocationDoesNotHaveVendor())
{
return;
}
string itemName = input.Substring(4).Trim();
if(string.IsNullOrEmpty(itemName))
{
Console.WriteLine("You must enter the name of the item to buy");
}
else
{
// Get the InventoryItem from the trader's inventory
InventoryItem itemToBuy =
_player.CurrentLocation.VendorWorkingHere.Inventory.SingleOrDefault(
x => x.Details.Name.ToLower() == itemName);
// Check if the vendor has the item
if(itemToBuy == null)
{
Console.WriteLine("The vendor does not have any {0}", itemName);
}
else
{
// Check if the player has enough gold to buy the item
if(_player.Gold < itemToBuy.Price)
{
Console.WriteLine("You do not have enough gold to buy a {0}", itemToBuy.Description);
}
else
{
// Success! Buy the item
_player.AddItemToInventory(itemToBuy.Details);
_player.Gold -= itemToBuy.Price;
Console.WriteLine("You bought one {0} for {1} gold", itemToBuy.Details.Name, itemToBuy.Price);
}
}
}
}
private static void SellItem(string input)
{
if(LocationDoesNotHaveVendor())
{
return;
}
string itemName = input.Substring(5).Trim();
if(string.IsNullOrEmpty(itemName))
{
Console.WriteLine("You must enter the name of the item to sell");
}
else
{
// Get the InventoryItem from the player's inventory
InventoryItem itemToSell =
_player.Inventory.SingleOrDefault(x => x.Details.Name.ToLower() == itemName &&
x.Quantity > 0 &&
x.Price != World.UNSELLABLE_ITEM_PRICE);
// Check if the player has the item entered
if(itemToSell == null)
{
Console.WriteLine("The player cannot sell any {0}", itemName);
}
else
{
// Sell the item
_player.RemoveItemFromInventory(itemToSell.Details);
_player.Gold += itemToSell.Price;
Console.WriteLine("You receive {0} gold for your {1}", itemToSell.Price, itemToSell.Details.Name);
}
}
}
private static bool LocationDoesNotHaveVendor()
{
bool locationDoesNotHaveVendor = _player.CurrentLocation.VendorWorkingHere == null;
Console.WriteLine("There is no vendor at this location");
return locationDoesNotHaveVendor;
}
private static void DisplayCurrentLocation()
{
Console.WriteLine("You are at: {0}", _player.CurrentLocation.Name);
if(_player.CurrentLocation.Description != "")
{
Console.WriteLine(_player.CurrentLocation.Description);
}
}
private static void LoadGameData()
{
_player = PlayerDataMapper.CreateFromDatabase();
if(_player == null)
{
if(File.Exists(PLAYER_DATA_FILE_NAME))
{
_player = Player.CreatePlayerFromXmlString(File.ReadAllText(PLAYER_DATA_FILE_NAME));
}
else
{
_player = Player.CreateDefaultPlayer();
}
}
}
private static void SaveGameData()
{
File.WriteAllText(PLAYER_DATA_FILE_NAME, _player.ToXmlString());
PlayerDataMapper.SaveToDatabase(_player);
}
}
}
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using Engine;
namespace SuperAdventure
{
public partial class SuperAdventure : Form
{
private const string PLAYER_DATA_FILE_NAME = "PlayerData.xml";
private Player _player;
public SuperAdventure()
{
InitializeComponent();
_player = PlayerDataMapper.CreateFromDatabase();
if(_player == null)
{
if(File.Exists(PLAYER_DATA_FILE_NAME))
{
_player = Player.CreatePlayerFromXmlString(File.ReadAllText(PLAYER_DATA_FILE_NAME));
}
else
{
_player = Player.CreateDefaultPlayer();
}
}
lblHitPoints.DataBindings.Add("Text", _player, "CurrentHitPoints");
lblGold.DataBindings.Add("Text", _player, "Gold");
lblExperience.DataBindings.Add("Text", _player, "ExperiencePoints");
lblLevel.DataBindings.Add("Text", _player, "Level");
dgvInventory.RowHeadersVisible = false;
dgvInventory.AutoGenerateColumns = false;
dgvInventory.DataSource = _player.Inventory;
dgvInventory.Columns.Add(new DataGridViewTextBoxColumn
{
HeaderText = "Name",
Width = 197,
DataPropertyName = "Description"
});
dgvInventory.Columns.Add(new DataGridViewTextBoxColumn
{
HeaderText = "Quantity",
DataPropertyName = "Quantity"
});
dgvInventory.ScrollBars = ScrollBars.Vertical;
dgvQuests.RowHeadersVisible = false;
dgvQuests.AutoGenerateColumns = false;
dgvQuests.DataSource = _player.Quests;
dgvQuests.Columns.Add(new DataGridViewTextBoxColumn
{
HeaderText = "Name",
Width = 197,
DataPropertyName = "Name"
});
dgvQuests.Columns.Add(new DataGridViewTextBoxColumn
{
HeaderText = "Done?",
DataPropertyName = "IsCompleted"
});
cboWeapons.DataSource = _player.Weapons;
cboWeapons.DisplayMember = "Name";
cboWeapons.ValueMember = "Id";
if(_player.CurrentWeapon != null)
{
cboWeapons.SelectedItem = _player.CurrentWeapon;
}
cboWeapons.SelectedIndexChanged += cboWeapons_SelectedIndexChanged;
cboPotions.DataSource = _player.Potions;
cboPotions.DisplayMember = "Name";
cboPotions.ValueMember = "Id";
_player.PropertyChanged += PlayerOnPropertyChanged;
_player.OnMessage += DisplayMessage;
_player.MoveTo(_player.CurrentLocation);
}
private void DisplayMessage(object sender, MessageEventArgs messageEventArgs)
{
rtbMessages.Text += messageEventArgs.Message + Environment.NewLine;
if(messageEventArgs.AddExtraNewLine)
{
rtbMessages.Text += Environment.NewLine;
}
rtbMessages.SelectionStart = rtbMessages.Text.Length;
rtbMessages.ScrollToCaret();
}
private void PlayerOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
if(propertyChangedEventArgs.PropertyName == "Weapons")
{
cboWeapons.DataSource = _player.Weapons;
if(!_player.Weapons.Any())
{
cboWeapons.Visible = false;
btnUseWeapon.Visible = false;
}
}
if(propertyChangedEventArgs.PropertyName == "Potions")
{
cboPotions.DataSource = _player.Potions;
if(!_player.Potions.Any())
{
cboPotions.Visible = false;
btnUsePotion.Visible = false;
}
}
if(propertyChangedEventArgs.PropertyName == "CurrentLocation")
{
// Show/hide available movement buttons
btnNorth.Visible = (_player.CurrentLocation.LocationToNorth != null);
btnEast.Visible = (_player.CurrentLocation.LocationToEast != null);
btnSouth.Visible = (_player.CurrentLocation.LocationToSouth != null);
btnWest.Visible = (_player.CurrentLocation.LocationToWest != null);
btnTrade.Visible = (_player.CurrentLocation.VendorWorkingHere != null);
// Display current location name and description
rtbLocation.Text = _player.CurrentLocation.Name + Environment.NewLine;
rtbLocation.Text += _player.CurrentLocation.Description + Environment.NewLine;
if(!_player.CurrentLocation.HasAMonster)
{
cboWeapons.Visible = false;
cboPotions.Visible = false;
btnUseWeapon.Visible = false;
btnUsePotion.Visible = false;
}
else
{
cboWeapons.Visible = _player.Weapons.Any();
cboPotions.Visible = _player.Potions.Any();
btnUseWeapon.Visible = _player.Weapons.Any();
btnUsePotion.Visible = _player.Potions.Any();
}
}
}
private void btnNorth_Click(object sender, EventArgs e)
{
_player.MoveNorth();
}
private void btnEast_Click(object sender, EventArgs e)
{
_player.MoveEast();
}
private void btnSouth_Click(object sender, EventArgs e)
{
_player.MoveSouth();
}
private void btnWest_Click(object sender, EventArgs e)
{
_player.MoveWest();
}
private void btnUseWeapon_Click(object sender, EventArgs e)
{
// Get the currently selected weapon from the cboWeapons ComboBox
Weapon currentWeapon = (Weapon)cboWeapons.SelectedItem;
_player.UseWeapon(currentWeapon);
}
private void btnUsePotion_Click(object sender, EventArgs e)
{
// Get the currently selected potion from the combobox
HealingPotion potion = (HealingPotion)cboPotions.SelectedItem;
_player.UsePotion(potion);
}
private void SuperAdventure_FormClosing(object sender, FormClosingEventArgs e)
{
File.WriteAllText(PLAYER_DATA_FILE_NAME, _player.ToXmlString());
PlayerDataMapper.SaveToDatabase(_player);
}
private void cboWeapons_SelectedIndexChanged(object sender, EventArgs e)
{
_player.CurrentWeapon = (Weapon)cboWeapons.SelectedItem;
}
private void btnTrade_Click(object sender, EventArgs e)
{
TradingScreen tradingScreen = new TradingScreen(_player);
tradingScreen.StartPosition = FormStartPosition.CenterParent;
tradingScreen.ShowDialog(this);
}
}
}
using System.Collections.Generic;
using System.Linq;
namespace Engine
{
public static class World
{
private static readonly List<Item> _items = new List<Item>();
private static readonly List<Monster> _monsters = new List<Monster>();
private static readonly List<Quest> _quests = new List<Quest>();
private static readonly List<Location> _locations = new List<Location>();
public const int UNSELLABLE_ITEM_PRICE = -1;
public const int ITEM_ID_RUSTY_SWORD = 1;
public const int ITEM_ID_RAT_TAIL = 2;
public const int ITEM_ID_PIECE_OF_FUR = 3;
public const int ITEM_ID_SNAKE_FANG = 4;
public const int ITEM_ID_SNAKESKIN = 5;
public const int ITEM_ID_CLUB = 6;
public const int ITEM_ID_HEALING_POTION = 7;
public const int ITEM_ID_SPIDER_FANG = 8;
public const int ITEM_ID_SPIDER_SILK = 9;
public const int ITEM_ID_ADVENTURER_PASS = 10;
public const int MONSTER_ID_RAT = 1;
public const int MONSTER_ID_SNAKE = 2;
public const int MONSTER_ID_GIANT_SPIDER = 3;
public const int QUEST_ID_CLEAR_ALCHEMIST_GARDEN = 1;
public const int QUEST_ID_CLEAR_FARMERS_FIELD = 2;
public const int LOCATION_ID_HOME = 1;
public const int LOCATION_ID_TOWN_SQUARE = 2;
public const int LOCATION_ID_GUARD_POST = 3;
public const int LOCATION_ID_ALCHEMIST_HUT = 4;
public const int LOCATION_ID_ALCHEMISTS_GARDEN = 5;
public const int LOCATION_ID_FARMHOUSE = 6;
public const int LOCATION_ID_FARM_FIELD = 7;
public const int LOCATION_ID_BRIDGE = 8;
public const int LOCATION_ID_SPIDER_FIELD = 9;
static World()
{
PopulateItems();
PopulateMonsters();
PopulateQuests();
PopulateLocations();
}
private static void PopulateItems()
{
_items.Add(new Weapon(ITEM_ID_RUSTY_SWORD, "Rusty sword", "Rusty swords", 0, 5, 5));
_items.Add(new Item(ITEM_ID_RAT_TAIL, "Rat tail", "Rat tails", 1));
_items.Add(new Item(ITEM_ID_PIECE_OF_FUR, "Piece of fur", "Pieces of fur", 1));
_items.Add(new Item(ITEM_ID_SNAKE_FANG, "Snake fang", "Snake fangs", 1));
_items.Add(new Item(ITEM_ID_SNAKESKIN, "Snakeskin", "Snakeskins", 2));
_items.Add(new Weapon(ITEM_ID_CLUB, "Club", "Clubs", 3, 10, 8));
_items.Add(new HealingPotion(ITEM_ID_HEALING_POTION, "Healing potion", "Healing potions", 5, 3));
_items.Add(new Item(ITEM_ID_SPIDER_FANG, "Spider fang", "Spider fangs", 1));
_items.Add(new Item(ITEM_ID_SPIDER_SILK, "Spider silk", "Spider silks", 1));
_items.Add(new Item(ITEM_ID_ADVENTURER_PASS, "Adventurer pass", "Adventurer passes", UNSELLABLE_ITEM_PRICE));
}
private static void PopulateMonsters()
{
Monster rat = new Monster(MONSTER_ID_RAT, "Rat", 5, 3, 10, 3, 3);
rat.LootTable.Add(new LootItem(ItemByID(ITEM_ID_RAT_TAIL), 75, false));
rat.LootTable.Add(new LootItem(ItemByID(ITEM_ID_PIECE_OF_FUR), 75, true));
Monster snake = new Monster(MONSTER_ID_SNAKE, "Snake", 5, 3, 10, 3, 3);
snake.LootTable.Add(new LootItem(ItemByID(ITEM_ID_SNAKE_FANG), 75, false));
snake.LootTable.Add(new LootItem(ItemByID(ITEM_ID_SNAKESKIN), 75, true));
Monster giantSpider = new Monster(MONSTER_ID_GIANT_SPIDER, "Giant spider", 20, 5, 40, 10, 10);
giantSpider.LootTable.Add(new LootItem(ItemByID(ITEM_ID_SPIDER_FANG), 75, true));
giantSpider.LootTable.Add(new LootItem(ItemByID(ITEM_ID_SPIDER_SILK), 25, false));
_monsters.Add(rat);
_monsters.Add(snake);
_monsters.Add(giantSpider);
}
private static void PopulateQuests()
{
Quest clearAlchemistGarden =
new Quest(
QUEST_ID_CLEAR_ALCHEMIST_GARDEN,
"Clear the alchemist's garden",
"Kill rats in the alchemist's garden and bring back 3 rat tails. You will receive a healing potion and 10 gold pieces.", 20, 10);
clearAlchemistGarden.QuestCompletionItems.Add(new QuestCompletionItem(ItemByID(ITEM_ID_RAT_TAIL), 3));
clearAlchemistGarden.RewardItem = ItemByID(ITEM_ID_HEALING_POTION);
Quest clearFarmersField =
new Quest(
QUEST_ID_CLEAR_FARMERS_FIELD,
"Clear the farmer's field",
"Kill snakes in the farmer's field and bring back 3 snake fangs. You will receive an adventurer's pass and 20 gold pieces.", 20, 20);
clearFarmersField.QuestCompletionItems.Add(new QuestCompletionItem(ItemByID(ITEM_ID_SNAKE_FANG), 3));
clearFarmersField.RewardItem = ItemByID(ITEM_ID_ADVENTURER_PASS);
_quests.Add(clearAlchemistGarden);
_quests.Add(clearFarmersField);
}
private static void PopulateLocations()
{
// Create each location
Location home = new Location(LOCATION_ID_HOME, "Home", "Your house. You really need to clean up the place.");
Location townSquare = new Location(LOCATION_ID_TOWN_SQUARE, "Town square", "You see a fountain.");
Vendor bobTheRatCatcher = new Vendor("Bob the Rat-Catcher");
bobTheRatCatcher.AddItemToInventory(ItemByID(ITEM_ID_PIECE_OF_FUR), 5);
bobTheRatCatcher.AddItemToInventory(ItemByID(ITEM_ID_RAT_TAIL), 3);
townSquare.VendorWorkingHere = bobTheRatCatcher;
Location alchemistHut = new Location(LOCATION_ID_ALCHEMIST_HUT, "Alchemist's hut", "There are many strange plants on the shelves.");
alchemistHut.QuestAvailableHere = QuestByID(QUEST_ID_CLEAR_ALCHEMIST_GARDEN);
Location alchemistsGarden = new Location(LOCATION_ID_ALCHEMISTS_GARDEN, "Alchemist's garden", "Many plants are growing here.");
alchemistsGarden.AddMonster(MONSTER_ID_RAT, 100);
Location farmhouse = new Location(LOCATION_ID_FARMHOUSE, "Farmhouse", "There is a small farmhouse, with a farmer in front.");
farmhouse.QuestAvailableHere = QuestByID(QUEST_ID_CLEAR_FARMERS_FIELD);
Location farmersField = new Location(LOCATION_ID_FARM_FIELD, "Farmer's field", "You see rows of vegetables growing here.");
farmersField.AddMonster(MONSTER_ID_SNAKE, 100);
Location guardPost = new Location(LOCATION_ID_GUARD_POST, "Guard post", "There is a large, tough-looking guard here.", ItemByID(ITEM_ID_ADVENTURER_PASS));
Location bridge = new Location(LOCATION_ID_BRIDGE, "Bridge", "A stone bridge crosses a wide river.");
Location spiderField = new Location(LOCATION_ID_SPIDER_FIELD, "Forest", "You see spider webs covering covering the trees in this forest.");
spiderField.AddMonster(MONSTER_ID_GIANT_SPIDER, 100);
// Link the locations together
home.LocationToNorth = townSquare;
townSquare.LocationToNorth = alchemistHut;
townSquare.LocationToSouth = home;
townSquare.LocationToEast = guardPost;
townSquare.LocationToWest = farmhouse;
farmhouse.LocationToEast = townSquare;
farmhouse.LocationToWest = farmersField;
farmersField.LocationToEast = farmhouse;
alchemistHut.LocationToSouth = townSquare;
alchemistHut.LocationToNorth = alchemistsGarden;
alchemistsGarden.LocationToSouth = alchemistHut;
guardPost.LocationToEast = bridge;
guardPost.LocationToWest = townSquare;
bridge.LocationToWest = guardPost;
bridge.LocationToEast = spiderField;
spiderField.LocationToWest = bridge;
// Add the locations to the static list
_locations.Add(home);
_locations.Add(townSquare);
_locations.Add(guardPost);
_locations.Add(alchemistHut);
_locations.Add(alchemistsGarden);
_locations.Add(farmhouse);
_locations.Add(farmersField);
_locations.Add(bridge);
_locations.Add(spiderField);
}
public static Item ItemByID(int id)
{
return _items.SingleOrDefault(x => x.ID == id);
}
public static Monster MonsterByID(int id)
{
return _monsters.SingleOrDefault(x => x.ID == id);
}
public static Quest QuestByID(int id)
{
return _quests.SingleOrDefault(x => x.ID == id);
}
public static Location LocationByID(int id)
{
return _locations.SingleOrDefault(x => x.ID == id);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment