using System using Nemerle using Nemerle.Utility abstract class Person : MapObject [Accessor] \ protected mutable stamina : int = Dice.Roll (5, 3) [Accessor] \ protected mutable strength : int = Dice.Roll (5, 3) [Accessor] \ protected mutable vitality : int = Dice.Roll (5, 3) [Accessor] \ protected mutable max_vitality : int = vitality protected mutable healing_every : int = Dice.Roll (5, 3) protected mutable healing_for : int public virtual Health : string get match (vitality * 4 / max_vitality) | 0 => "badly damaged" | 1 => "bleeding" | 2 => "damaged" | _ => "still OK" public virtual Die () : void Map [X, Y] = Map [X, Y].Filter (_ != this : object) public override Attack (from : MapObject, damage : int) : void if (damage < stamina) when (from.IsPlayer) Map.Message ($ "You didn't even scratch $Name.") else healing_for = 0 vitality -= damage - stamina if (vitality <= 0) when (from.IsPlayer) Map.Message ($ "You killed $Name.") Die () else when (from.IsPlayer) Map.Message ($ "You hit $Name, it's $Health.") public override PerformMove () : void when (vitality < max_vitality) if (healing_for >= healing_every) healing_for = 0 vitality++ else healing_for++ public MoveOrKill (x : int, y : int) : void match (Map [x, y].Filter (fun (x) { ! x.CanEnter })) | [] => MoveTo (x, y) | x :: _ => x.Attack (this, Strength / 2 + Dice.Roll (6)) public RandomMove () : void def try_move (x, y) MoveOrKill (x, y) match (Dice.Roll (4)) | 1 => try_move (X - 1, Y) | 2 => try_move (X, Y - 1) | 3 => try_move (X + 1, Y) | _ => try_move (X, Y + 1) class EnemyUnknown : Person mutable hostile : bool public override Draw () : void when (Map.PlayerCanSee (this)) ConsoleBuffer.DrawChar (ColoredChar ('K', ConsoleColor.Red)) public override PerformMove () : void if (hostile && DistanceTo (Map.Player) == 1) MoveOrKill (Map.Player.X, Map.Player.Y) else RandomMove () public override Attack (from : MapObject, damage : int) : void when (from.IsPlayer) hostile = true base.Attack (from, damage) public override Name : string { get { "enemy unknown" } } class Player : Person public override Draw () : void ConsoleBuffer.DrawChar (ColoredChar ('@', ConsoleColor.Cyan)) public override PerformMove () : void base.PerformMove (); // heal def key = Console.ReadKey (true) def (x, y) = match (key.Key) | LeftArrow => (X - 1, Y) | RightArrow => (X + 1, Y) | UpArrow => (X, Y - 1) | DownArrow => (X, Y + 1) | _ => (X, Y) if (x != X || y != Y) MoveOrKill (x, y) else match (key.KeyChar) | 'r' => Map.ResetMap () | 's' => Map.ShowAll = ! Map.ShowAll | 'q' => System.Environment.Exit (0) | _ => Map.Message ("Move with arrows, [h] for help!") public override Attack (from : MapObject, damage : int) : void Map.Message ($ "The $(from.Name) attacks you.") base.Attack (from, damage) public override Name : string { get { "player" } } public override IsPlayer : bool { get { true } }