Castle Lords Reign – A Medieval Tinder Game
(1*) var io = new ConsoleInputOutput(); This constitutes the declaration of a variable and the creation of a new instance (object) in a single step.
var io (Declaration): Here, a new variable named `io` is declared. Thanks to the `var` keyword, the compiler automatically infers the type (implicit typing) based on the expression on the right-hand side.
= new ConsoleInputOutput(); (New Instance): The `new` operator creates a new object (instance) of the `ConsoleInputOutput` class and invokes its constructor.
Summary: You declare the variable io, initialize it with an instance of the ConsoleInputOutput class, and assign that instance to it.
Note: This applies specifically to C#, where `var` is used for implicitly typed local variables.
An example in C#:
// Castle Lords Reign Game in C#
using System;
using System.Collections.Generic;
using System.Linq;
namespace Castle Lords Reign
{
/// <summary>Program Entry Point with Menu Control</summary>
class Program
{
static void Main()
{
var io = new ConsoleInputOutput(); // (1*)
// Register all available events (easily extensible)
var events = new List<GameEvent>
{
new PlagueEvent(),
new MedicineEvent(),
new GoldEvent(),
new WeaponEvent()
};
var eventManager = new EventManager(events);
var game = new Game(io, io, eventManager);
while (true)
{
ShowMainMenu(io);
var choice = io.ReadKey();
if (choice == "1")
{
game.Run();
AskForRestart(io);
}
else if (choice == "9")
break;
else
io.WriteLine("Invalid input. Please press 1 or 9.");
}
}
/// <summary> Concrete Implementation of Console Input/Output</summary>
public class ConsoleInputOutput : IUserInput, IOutput
{
public string ReadKey() => Console.ReadKey().KeyChar.ToString();
public void WriteLine(string line) => Console.WriteLine(line);
public void Clear() => Console.Clear();
}
private static void ShowMainMenu(IOutput output)
{
output.Clear();
output.WriteLine("*******Castle Lords Reign******");
output.WriteLine("*******Dominions français******");
output.WriteLine("*******************************\n");
output.WriteLine("Click 1 to run the game");
output.WriteLine("Click 9 to quit the game\n");
output.WriteLine("*******************************");
}
private static void AskForRestart(IOutput output)
{
output.WriteLine("Do you want to restart? 1 = Yes, 9 = Exit");
while (true)
{
var input = Console.ReadKey().KeyChar.ToString();
if (input == "1") return; // Restart, main menu reappears
if (input == "9") Environment.Exit(0);
output.WriteLine("\nInvalid input.");
}
}
}
/// <summary>
/// Game state (the four power indicators).
/// </summary>
public class GameState
{
public int Gold { get; private set; }
public int Church { get; private set; }
public int Military { get; private set; }
public int People { get; private set; }
public GameState(int gold, int church, int military, int people)
{
Gold = gold;
Church = church;
Military = military;
People = people;
}
/// <summary>Changes the values by the specified deltas.</summary>
public void Modify(int deltaGold, int deltaChurch, int deltaMilitary, int deltaPeople)
{
Gold += deltaGold;
Church += deltaChurch;
Military += deltaMilitary;
People += deltaPeople;
}
/// <summary>Checks whether the king is still alive (all values between 1 and 99).</summary>
public bool IsAlive => Gold is > 0 and < 100 &&
Church is > 0 and < 100 &&
Military is > 0 and < 100 &&
People is > 0 and < 100;
}
/// <summary>Abstract base class for all game events.</summary>
public abstract class GameEvent
{
public string Name { get; }
public string Description { get; }
protected GameEvent(string name, string description)
{
Name = name;
Description = description;
}
/// <summary>Executes the event (asks the player and modifies the state).</summary>
public abstract void Execute(GameState state, IUserInput input, IOutput output);
}
/// <summary>Event: Plague</summary>
public class PlagueEvent : GameEvent
{
private const int PeopleLossArmy = 8;
private const int MilitaryLossArmy = 15;
private const int ChurchLossArmy = 5;
private const int PeopleLossNoArmy = 11;
private const int MilitaryLossNoArmy = 9;
private const int ChurchLossNoArmy = 7;
public PlagueEvent() : base("Plague", "Should it primarily affect the military?") { }
public override void Execute(GameState state, IUserInput input, IOutput output)
{
output.WriteLine($"\n{Description}\n1 = YES\n9 = NO");
var choice = input.ReadKey();
if (choice == "1")
state.Modify(0, -ChurchLossArmy, -MilitaryLossArmy, -PeopleLossArmy);
else
state.Modify(0, -ChurchLossNoArmy, -MilitaryLossNoArmy, -PeopleLossNoArmy);
}
}
/// <summary>Event: Medicine</summary>
public class MedicineEvent : GameEvent
{
private const int GoldCostYes = 7;
private const int PeopleGainYes = 12;
private const int MilitaryGainYes = 1;
private const int ChurchGainYes = 3;
private const int PeopleLossNo = 4;
private const int MilitaryGainNo = 5;
private const int ChurchGainNo = 7;
public MedicineEvent() : base("Medicine", "As king, do you want to buy enough medicine for your people?") { }
public override void Execute(GameState state, IUserInput input, IOutput output)
{
output.WriteLine($"\n{Description}\n1 = YES\n9 = NO");
var choice = input.ReadKey();
if (choice == "1")
state.Modify(-GoldCostYes, ChurchGainYes, MilitaryGainYes, PeopleGainYes);
else
state.Modify(0, ChurchGainNo, MilitaryGainNo, -PeopleLossNo);
}
}
/// <summary>Event: Gold</summary>
public class GoldEvent : GameEvent
{
private const int GoldGainYes = 12;
private const int PeopleLossYes = 5;
private const int MilitaryLossYes = 10;
private const int ChurchLossYes = 8;
private const int PeopleGainNo = 8;
private const int MilitaryGainNo = 5;
private const int ChurchGainNo = 7;
public GoldEvent() : base("Gold", "Should the new gold delivery belong entirely to you?") { }
public override void Execute(GameState state, IUserInput input, IOutput output)
{
output.WriteLine($"\n{Description}\n1 = YES\n9 = NO");
var choice = input.ReadKey();
if (choice == "1")
state.Modify(GoldGainYes, -ChurchLossYes, -MilitaryLossYes, -PeopleLossYes);
else
state.Modify(0, ChurchGainNo, MilitaryGainNo, PeopleGainNo);
}
}
/// <summary>Event: Weapons</summary>
public class WeaponEvent : GameEvent
{
private const int GoldCostYes = 5;
private const int PeopleGainYes = 12;
private const int MilitaryLossYes = 10;
private const int ChurchGainYes = 3;
private const int PeopleLossNo = 10;
private const int MilitaryGainNo = 15;
private const int ChurchLossNo = 10;
public WeaponEvent() : base("Weapons", "Give weapons to your people against the military?") { }
public override void Execute(GameState state, IUserInput input, IOutput output)
{
output.WriteLine($"\n{Description}\n1 = YES\n9 = NO");
var choice = input.ReadKey();
if (choice == "1")
state.Modify(-GoldCostYes, ChurchGainYes, -MilitaryLossYes, PeopleGainYes);
else
state.Modify(0, -ChurchLossNo, MilitaryGainNo, -PeopleLossNo);
}
}
/// <summary>Interface for user input (enables future extensions, e.g., mouse).</summary>
public interface IUserInput
{
string ReadKey(); // Reads a single key (as a string)
}
/// <summary>Interface for output (enables GUI later, e.g.).</summary>
public interface IOutput
{
void WriteLine(string line);
void Clear();
}
/// <summary>Manages all events (central list).</summary>
public class EventManager
{
private readonly List<GameEvent> _events;
private readonly Random _random = Random.Shared; // Thread-safe and efficient
public EventManager(IEnumerable<GameEvent> events)
{
_events = events.ToList();
}
/// <summary>Returns a random event.</summary>
public GameEvent GetRandomEvent() => _events[_random.Next(_events.Count)];
}
/// <summary>Main game logic.</summary>
public class Game
{
private readonly IUserInput _input;
private readonly IOutput _output;
private readonly EventManager _eventManager;
public Game(IUserInput input, IOutput output, EventManager eventManager)
{
_input = input;
_output = output;
_eventManager = eventManager;
}
/// <summary>Starts a new round of the game.</summary>
public void Run()
{
// Random starting values (1-100)
var rnd = Random.Shared;
var state = new GameState(
gold: rnd.Next(1, 101),
church: rnd.Next(1, 101),
military: rnd.Next(1, 101),
people: rnd.Next(1, 101)
);
_output.Clear();
_output.WriteLine("Always keep your four powers in balance. Otherwise, death awaits!\n");
DisplayStats(state);
// Main game loop: as long as the king is alive
while (state.IsAlive)
{
var gameEvent = _eventManager.GetRandomEvent();
_output.WriteLine(gameEvent.Name);
gameEvent.Execute(state, _input, _output);
DisplayStats(state);
}
_output.WriteLine("\nThe king is dead!\n");
}
private void DisplayStats(GameState state)
{
_output.WriteLine($"Gold: {state.Gold} Church: {state.Church} Military: {state.Military} People: {state.People}\n");
}
}
}