[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 ("");
+      Console.ForegroundColor = fg;
+      when (is_high)
+        Console.Write ("");
+      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