[svn] r5823: nemerle/trunk/snippets/the-game: . Makefile console.n
generator.n map.n
malekith
svnadmin at nemerle.org
Sun Oct 16 16:02:56 CEST 2005
Log:
A next exercise? :-)
Author: malekith
Date: Sun Oct 16 16:02:55 2005
New Revision: 5823
Added:
nemerle/trunk/snippets/the-game/ (props changed)
nemerle/trunk/snippets/the-game/Makefile
nemerle/trunk/snippets/the-game/console.n
nemerle/trunk/snippets/the-game/generator.n
nemerle/trunk/snippets/the-game/map.n
Added: nemerle/trunk/snippets/the-game/Makefile
==============================================================================
--- (empty file)
+++ nemerle/trunk/snippets/the-game/Makefile Sun Oct 16 16:02:55 2005
@@ -0,0 +1,2 @@
+all:
+ ncc -o TheGame.exe console.n generator.n map.n
Added: nemerle/trunk/snippets/the-game/console.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/snippets/the-game/console.n Sun Oct 16 16:02:55 2005
@@ -0,0 +1,127 @@
+using System;
+using Nemerle;
+
+struct ColoredChar {
+ public Char : char;
+ public Foreground : ConsoleColor;
+ public Background : ConsoleColor;
+
+ public this (ch : Char,
+ fg : ConsoleColor = ConsoleColor.Gray,
+ bg : ConsoleColor = ConsoleColor.Black)
+ {
+ this.Char = ch;
+ Foreground = fg;
+ Background = bg;
+ }
+
+ [OverrideObjectEquals]
+ public Equals (other : ColoredChar) : bool
+ {
+ Char == other.Char &&
+ Foreground == other.Foreground &&
+ Background == other.Background
+ }
+}
+
+module ConsoleBuffer
+{
+ mutable current_fg : ConsoleColor = ConsoleColor.Gray;
+ mutable current_bg : ConsoleColor = ConsoleColor.Black;
+
+ mutable cur_x : int;
+ mutable cur_y : int;
+
+ screen : array [2, ColoredChar];
+ real_screen : array [2, ColoredChar];
+
+ width : int;
+ height : int;
+
+ public Flush () : void
+ {
+ for (mutable y = 0; y < height; ++y) {
+ mutable first_x = -1;
+ mutable last_x = -1;
+
+ for (mutable x = 0; x < width; ++x) {
+ when (! screen [x, y].Equals (real_screen [x, y])) {
+ when (first_x == -1) first_x = x;
+ last_x = x;
+ }
+ }
+
+ when (last_x != -1) {
+ Console.SetCursorPosition (1 + first_x, y + 1);
+ while (first_x <= last_x) {
+ def ch = screen [first_x, y];
+ real_screen [first_x, y] = ch;
+ DoSetColor (ch.Foreground, ch.Background);
+ Console.Write (ch.Char);
+ first_x++;
+ }
+ }
+ }
+
+ Console.SetCursorPosition (width - 1, height - 1);
+ }
+
+ public Clear () : void
+ {
+ for (mutable y = 0; y < height; ++y)
+ for (mutable x = 0; x < width; ++x)
+ screen [x, y] = ColoredChar (' ');
+ }
+
+ public Goto (x : int, y : int) : void
+ {
+ cur_x = x;
+ cur_y = y;
+ }
+
+ public DrawChar (ch : ColoredChar) : void
+ {
+ screen [cur_x, cur_y] = ch;
+ cur_x++;
+ when (cur_x == width) {
+ cur_x = 0;
+ cur_y++;
+ when (cur_y == height)
+ cur_y = 0;
+ }
+ }
+
+ public DrawString (s : string,
+ fg : ConsoleColor = ConsoleColor.Gray,
+ bg : ConsoleColor = ConsoleColor.Black) : void
+ {
+ foreach (ch in s)
+ DrawChar (ColoredChar (ch, fg, bg))
+ }
+
+ DoSetColor (fg : ConsoleColor, bg : ConsoleColor) : void
+ {
+ when (fg != current_fg) {
+ def is_high = fg :> int > ConsoleColor.Gray :> int;
+
+ when (!is_high)
+ Console.Write ("[0m");
+ Console.ForegroundColor = fg;
+ when (is_high)
+ Console.Write ("[1m");
+ current_fg = fg;
+ }
+ when (bg != current_bg) {
+ Console.BackgroundColor = fg;
+ current_bg = bg;
+ }
+ }
+
+ this ()
+ {
+ width = Console.WindowWidth - 1;
+ height = Console.WindowHeight - 1;
+ screen = array (width, height);
+ real_screen = array (width, height);
+ }
+}
Added: nemerle/trunk/snippets/the-game/generator.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/snippets/the-game/generator.n Sun Oct 16 16:02:55 2005
@@ -0,0 +1,112 @@
+
+class MapGenerator
+{
+ fork_pbb = 0.05;
+ turn_pbb = 0.05;
+
+ map : array [2, bool];
+ mutable room_locations : list [int * int] = [];
+
+ rand : System.Random = System.Random ();
+
+ MaybeRoom (x : int, y : int) : void
+ {
+ when (rand.NextDouble () < 0.9)
+ room_locations ::= (x, y)
+ }
+
+ Path (x : int, y : int, dir : int) : void
+ {
+ if (x < 1 || y < 1 || x > width - 2 || y > height - 2) {
+ MaybeRoom (x, y)
+ } else if (map [x, y]) {
+ } else {
+ if (rand.NextDouble () < fork_pbb) {
+ when (rand.NextDouble () < 0.5)
+ Path (x, y, dir + 1);
+ when (rand.NextDouble () < 0.5) {
+ map [x, y] = false;
+ Path (x, y, dir + 3)
+ }
+ when (rand.NextDouble () < 0.1)
+ MaybeRoom (x, y);
+ map [x, y] = false;
+ Path (x, y, dir)
+ } else if (rand.NextDouble () < turn_pbb) {
+ if (rand.NextDouble () < 0.5)
+ Path (x, y, dir + 1)
+ else
+ Path (x, y, dir + 3)
+ } else {
+ map [x, y] = true;
+ def (x, y) =
+ match (dir % 4) {
+ | 0 => (x + 1, y)
+ | 1 => (x, y - 1)
+ | 2 => (x - 1, y)
+ | 3 => (x, y + 1)
+ | _ => assert (false)
+ }
+ Path (x, y, dir);
+ when (rand.NextDouble () < 0.05)
+ MaybeRoom (x, y)
+ }
+ }
+ }
+
+ width : int;
+ height : int;
+
+ public this (w : int, h : int)
+ {
+ width = w;
+ height = h;
+ map = array (w, h);
+ }
+
+ MapOK () : bool
+ {
+ mutable free = 0;
+
+ for (mutable i = 0; i < width; ++i)
+ for (mutable j = 0; j < height; ++j)
+ when (map [i, j]) free++;
+
+ if (free * 10 > width * height)
+ true
+ else {
+ room_locations = [];
+ for (mutable i = 0; i < width; ++i)
+ for (mutable j = 0; j < height; ++j)
+ map [i, j] = false;
+ false
+ }
+ }
+
+ DigRooms () : void
+ {
+ def dig (x, y) {
+ when (x >= 1 && y >= 1 && x <= width - 2 && y <= height - 2)
+ map [x, y] = true
+ }
+
+ foreach ((x, y) in room_locations) {
+ def rx = 1 + rand.Next (2) + rand.Next (2) + rand.Next (2);
+ def ry = rand.Next (2) + rand.Next (2);
+ for (mutable i = x - rx; i <= x + rx; ++i)
+ for (mutable j = y - ry; j <= y + ry; ++j)
+ dig (i, j)
+ }
+ }
+
+ public Generate () : array [2, bool]
+ {
+ Path (width / 2, height / 2, rand.Next (4));
+ if (MapOK ()) {
+ DigRooms ();
+ map
+ }
+ else Generate ()
+ }
+}
+
Added: nemerle/trunk/snippets/the-game/map.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/snippets/the-game/map.n Sun Oct 16 16:02:55 2005
@@ -0,0 +1,236 @@
+using System;
+using Nemerle;
+using Nemerle.Utility;
+
+abstract class MapObject
+{
+ [Accessor]
+ mutable map : WorldMap;
+
+ [Accessor]
+ mutable x : int;
+ [Accessor]
+ mutable y : int;
+
+ public abstract Draw () : void;
+
+ public virtual Init (map : WorldMap, x : int, y : int) : void
+ {
+ this.map = map;
+ this.x = x;
+ this.y = y;
+ PostInit ();
+ }
+
+ protected virtual PostInit () : void {}
+
+ public virtual CanEnter : bool
+ {
+ get { false }
+ }
+
+ public virtual MoveTo (x : int, y : int) : void
+ {
+ Map [this.x, this.y] = Map [this.x, this.y].Filter (_ != this : object);
+ this.x = x;
+ this.y = y;
+ Map [x, y] ::= this;
+ }
+}
+
+class Territory : MapObject
+{
+ protected DisplayWhenVisible : ColoredChar;
+ protected DisplayWhenSeen : ColoredChar;
+ protected DisplayWhenUnseen : ColoredChar = ColoredChar (' ');
+
+ protected mutable ever_seen : bool;
+
+ public override Draw () : void
+ {
+ if (Map.PlayerCanSee (this)) {
+ ever_seen = true;
+ ConsoleBuffer.DrawChar (DisplayWhenVisible)
+ } else if (ever_seen)
+ ConsoleBuffer.DrawChar (DisplayWhenSeen)
+ else
+ ConsoleBuffer.DrawChar (DisplayWhenUnseen)
+ }
+}
+
+class Floor : Territory
+{
+ public this ()
+ {
+ DisplayWhenVisible = ColoredChar ('.', ConsoleColor.Yellow);
+ DisplayWhenSeen = ColoredChar ('.', ConsoleColor.Gray);
+ }
+
+ public override CanEnter : bool
+ {
+ get { true }
+ }
+}
+
+class Wall : Territory
+{
+ public this ()
+ {
+ DisplayWhenVisible = ColoredChar ('#', ConsoleColor.DarkYellow);
+ DisplayWhenSeen = DisplayWhenVisible;
+ }
+
+ Visible : bool
+ {
+ [Memoize]
+ get {
+ def check (x, y) { Map [x, y].Exists (_.CanEnter) }
+
+ check (X - 1, Y - 1) ||
+ check (X + 1, Y - 1) ||
+ check (X - 1, Y + 1) ||
+ check (X + 1, Y + 1) ||
+ check (X - 1, Y) ||
+ check (X, Y - 1) ||
+ check (X, Y + 1) ||
+ check (X + 1, Y)
+ }
+ }
+
+
+ public override Draw () : void
+ {
+ if (Visible)
+ base.Draw ()
+ else
+ ConsoleBuffer.DrawChar (DisplayWhenUnseen);
+ }
+}
+
+class Player : MapObject
+{
+ public override Draw () : void
+ {
+ ConsoleBuffer.DrawChar (ColoredChar ('@', ConsoleColor.Cyan));
+ }
+
+ public PerformMove () : void
+ {
+ 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)
+ if (Map [x, y].ForAll (_.CanEnter))
+ MoveTo (x, y)
+ else
+ Map.StatusMessage ("Cannot move there!")
+ else
+ match (key.KeyChar) {
+ | 'r' => Map.ResetMap ();
+ | 'q' => System.Environment.Exit (0);
+ | _ =>
+ Map.StatusMessage ("Move with arrows, [h] for help!")
+ }
+ }
+}
+
+class WorldMap {
+ width = 78;
+ height = 20;
+
+ mutable status : string = "";
+
+ map : array [2, list [MapObject]];
+ mutable player : Player;
+
+ public Item [x : int, y : int] : list [MapObject]
+ {
+ get {
+ if (x < 0 || y < 0 || x >= width || y >= height)
+ []
+ else
+ map [x, y]
+ }
+ set { map [x, y] = value }
+ }
+
+ public this ()
+ {
+ map = array (width, height);
+ ResetMap ();
+ }
+
+ public ResetMap () : void
+ {
+ def gen = MapGenerator (width, height);
+ def bool_map = gen.Generate ();
+
+ for (mutable x = 0; x < width; ++x)
+ for (mutable y = 0; y < height; ++y) {
+ def f =
+ if (bool_map [x, y])
+ Floor ()
+ else
+ Wall ();
+ map [x, y] = [f];
+ f.Init (this, x, y);
+ }
+
+ player = Player ();
+ player.Init (this, width / 2, height / 2);
+ map [player.X, player.Y] ::= player;
+ }
+
+ public StatusMessage (msg : string) : void
+ {
+ status += $"$msg ";
+ }
+
+ public Draw () : void
+ {
+ ConsoleBuffer.Clear ();
+ for (mutable y = 0; y < height; ++y) {
+ ConsoleBuffer.Goto (1, y);
+ for (mutable x = 0; x < width; ++x)
+ map [x, y].Head.Draw ();
+ }
+ ConsoleBuffer.Goto(0, height);
+ ConsoleBuffer.DrawString (status, ConsoleColor.Yellow);
+ status = "";
+
+ ConsoleBuffer.Flush ();
+ }
+
+ public PlayerCanSee (target : MapObject) : bool
+ {
+ def dx = player.X - target.X;
+ def dy = player.Y - target.Y;
+ (dx * dx + dy * dy) < 10
+ }
+
+ public MainLoop () : void
+ {
+ try {
+ while (true) {
+ Draw ();
+ player.PerformMove ();
+ }
+ } catch {
+ | e =>
+ Console.WriteLine (e);
+ _ = Console.ReadLine ();
+ }
+ }
+
+ public static Main () : void
+ {
+ def world = WorldMap ();
+ world.MainLoop ();
+ }
+}
More information about the svn
mailing list