// 01 basic setup
// rogue at its simplest and most readable
// player can move around dungeon, bump into walls,
// pick up gold and items, kill monsters, and
// use the stairs
// random bits of level, monsters, gold, and items
// placed randomly in the dungeon
// help screen shows how to deal with fullscreen
// commands like inventory and discoveries
using System;
class Program
{
static THING player = new THING();
static bool found_amulet = false;
static Random random = new Random();
static void Main(string[] args)
{
Console.WindowWidth = Console.BufferWidth = 80;
Console.WindowHeight = Console.BufferHeight = 25;
Console.Title = "steelgolem rogue - 01 basic setup";
CONSOLE.clear();
dungeon_level = 1;
new_level();
update_status();
while (true)
{
// put cursor under player to highlight
CONSOLE.move_cursor(player.x, player.y);
char key_ch = CONSOLE.read_key();
switch(key_ch)
{
case '?': show_help(); break;
case 'h': move_player(-1, 0); break;
case 'j': move_player(0, +1); break;
case 'k': move_player(0, -1); break;
case 'l': move_player(+1, 0); break;
case 'y': move_player(-1, -1); break;
case 'u': move_player(+1, -1); break;
case 'b': move_player(-1, +1); break;
case 'n': move_player(+1, +1); break;
case '>':
if (player.under_ch == '%')
{
if (found_amulet && dungeon_level == 1)
win_game();
if (found_amulet) dungeon_level--;
else dungeon_level++;
new_level();
update_status();
}
else
{
if (found_amulet) set_message("there is no way up");
else set_message("there is no way down");
}
break;
case (char)18: // ^R
set_message(last_message);
break;
case 'Q':
Environment.Exit(0);
break;
}
}
}
#region dungeon level
static int dungeon_level;
static void new_level()
{
CONSOLE.clear();
// add some random level bits
for (int c = 0; c < 80; c++)
{
int x = random.Next(80);
int y = 1 + random.Next(23);
char ch = "-|.+#"[random.Next(5)];
CONSOLE.put_char(x, y, ch);
}
// add some gold
for (int c = 0; c < 9; c++)
{
int x = random.Next(80);
int y = 1 + random.Next(23);
CONSOLE.put_char(x, y, '*');
}
// add some items
for (int c = 0; c < 9; c++)
{
int x = random.Next(80);
int y = 1 + random.Next(23);
char ch = ":!?)]=/"[random.Next(7)];
CONSOLE.put_char(x, y, ch);
}
// add some monsters
for (int c = 0; c < 9; c++)
{
int x = random.Next(80);
int y = 1 + random.Next(23);
char ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[random.Next(26)];
CONSOLE.put_char(x, y, ch);
}
// add the amulet
if (dungeon_level >= 26)
{
int x = random.Next(80);
int y = 1 + random.Next(23);
CONSOLE.put_char(x, y, ',');
}
// add the stairs
int stairs_x = random.Next(80);
int stairs_y = 1 + random.Next(23);
CONSOLE.put_char(stairs_x, stairs_y, '%');
// place the player
player.x = random.Next(80);
player.y = 1 + random.Next(23);
player.under_ch = ' ';
player.draw();
}
#endregion // dungeon level
#region commands
static void show_help()
{
string[] help_text = new string[]
{
"? show help",
"h move left",
"j move down",
"k move up",
"l move right",
"y move up & left",
"u move up & right",
"b move down & left",
"n move down & right",
"> use stairs",
"^R repeat last message",
"Q quit game",
};
CONSOLE.back_up_buffer();
CONSOLE.clear();
for (int h = 0; h < help_text.Length; h++)
CONSOLE.write_string(0, h, help_text[h]);
CONSOLE.write_string(0, 24, "[press any key]");
CONSOLE.read_key();
CONSOLE.restore_buffer();
}
static void move_player(int dx, int dy)
{
clear_message();
int dest_x = player.x + dx;
int dest_y = player.y + dy;
char dest_ch = CONSOLE.get_char(dest_x, dest_y);
// walls stop movement
if (is_wall(dest_ch))
return;
// fight monster
if (is_monster(dest_ch))
{
CONSOLE.put_char(dest_x, dest_y, ' ');
set_message("defeated " + get_name(dest_ch));
return;
}
player.erase();
player.get_eraser(dest_x, dest_y);
player.x = dest_x;
player.y = dest_y;
player.draw();
// pick up gold
if (dest_ch == '*')
{
player.under_ch = ' ';
set_message("picked up gold");
}
// pick up item
if (is_item(dest_ch))
{
player.under_ch = ' ';
set_message("picked up " + get_name(dest_ch));
if (dest_ch == ',')
found_amulet = true;
}
}
#endregion // commands
#region helper functions
static bool is_wall(char ch)
{
return "-|".Contains(ch.ToString());
}
static bool is_monster(char ch)
{
return char.IsLetter(ch);
}
static bool is_item(char ch)
{
return ":!?)]=/,".Contains(ch.ToString());
}
static string get_name(char dest_ch)
{
switch (dest_ch)
{
case 'A': return "giant ant";
case 'B': return "bat";
case 'C': return "centaur";
case 'D': return "dragon";
case 'E': return "floating eye";
case 'F': return "violet fungi";
case 'G': return "gnome";
case 'H': return "hobgoblin";
case 'I': return "invisible stalker";
case 'J': return "jackal";
case 'K': return "kobold";
case 'L': return "leprechaun";
case 'M': return "mimic";
case 'N': return "nymph";
case 'O': return "orc";
case 'P': return "purple worm";
case 'Q': return "quasit";
case 'R': return "rust monster";
case 'S': return "snake";
case 'T': return "troll";
case 'U': return "umber hulk";
case 'V': return "vampire";
case 'W': return "wraith";
case 'X': return "xorn";
case 'Y': return "yeti";
case 'Z': return "zombie";
case ':': return "food";
case '!': return "potion";
case '?': return "scroll";
case ')': return "weapon";
case ']': return "armor";
case '=': return "ring";
case '/': return "stick";
case ',': return "the amulet of yendor";
default: return null;
}
}
static void update_status()
{
clear_status();
CONSOLE.write_string(0, 24, "level: " + dungeon_level);
}
#endregion // helper functions
#region messages
static string last_message = "";
static void set_message(string text)
{
CONSOLE.write_string(0, 0, text);
last_message = text;
}
static void clear_message()
{
CONSOLE.cursor_off();
CONSOLE.write_string(0, 0, "".PadRight(80));
CONSOLE.cursor_on();
}
static void clear_status()
{
CONSOLE.write_string(0, 24, "".PadRight(79));
}
#endregion // messages
#region game over
static void win_game()
{
CONSOLE.clear();
CONSOLE.write_string("you win");
CONSOLE.read_key();
Environment.Exit(0);
}
#endregion // game over
}
class THING
{
public int x, y;
public char under_ch;
public void get_eraser(int x, int y)
{
this.under_ch = CONSOLE.get_char(x, y);
}
public void erase()
{
CONSOLE.put_char(this.x, this.y, this.under_ch);
}
public void draw()
{
CONSOLE.put_char(this.x, this.y, '@');
}
}
class CONSOLE
{
static char[,] buffer = new char[80, 25];
static int cursor_x, cursor_y;
public static char get_char(int x, int y)
{
return buffer[x, y];
}
public static void put_char(char ch)
{
buffer[cursor_x, cursor_y] = ch;
cursor_x++;
if (cursor_x == 80)
{
cursor_x = 0;
cursor_y++;
}
Console.Write(ch);
}
public static void put_char(int x, int y, char ch)
{
move_cursor(x, y);
put_char(ch);
}
public static void move_cursor(int x, int y)
{
cursor_x = x;
cursor_y = y;
Console.SetCursorPosition(x, y);
}
public static char read_key()
{
return Console.ReadKey(true).KeyChar;
}
public static void write_string(string text)
{
for (int c = 0; c < text.Length; c++)
put_char(text[c]);
}
public static void write_string(int x, int y, string text)
{
move_cursor(x, y);
write_string(text);
}
public static void cursor_on()
{
Console.CursorVisible = true;
}
public static void cursor_off()
{
Console.CursorVisible = false;
}
public static void clear()
{
for (int y = 0; y < 25; y++)
for (int x = 0; x < 80; x++)
buffer[x, y] = ' ';
cursor_x = cursor_y = 0;
Console.Clear();
}
static char[,] old_buffer = new char[80, 25];
public static void back_up_buffer()
{
Array.Copy(CONSOLE.buffer, old_buffer, 80 * 25);
}
public static void restore_buffer()
{
Array.Copy(old_buffer, CONSOLE.buffer, 80 * 25);
for (int y = 0; y < 25; y++)
for (int x = 0; x < 80; x++)
if (!(x == 79 && y == 24))
CONSOLE.put_char(x, y, CONSOLE.buffer[x, y]);
}
}
Comments