A RogueLike game written in less than 1kB of C# source. Versions 1 through 3 were written for the rec.games.roguelike.development <1kB RL Challenge:
A year or so after the challenge a <512byte Roguelike was posted to the group. This brought about a renewed interest, with others posting new 1kB RogueLikes. I decided to revisit mine and see if any further optimizations could be made, allowing me to add more features.
Note that for the challenge we were allowed to use a separate IO library, such as curses. I used a custom IO lib, which is included below.
1kRl Visual Studio Solution (zipped)
ProgramPretty.cs - Pretty printed version with comments
Any key to begin; arrow keys, numpad keys or vi keys to move, q or [ESC] to quit. The current dungeon level and your health are shown at the bottom. If your health reaches 0 then the game is over.
using System;using S=System.String;using System.Collections.Generic;partial class M{Dictionary<S,S>d=new Dictionary<S,S>();List<S>e=new List<S>();int p=9,m=999,x,y,z,u,v,i,j;S a="@",w="#",f=".",s=">",c;Random r=new Random();M(int k,int l,int h){u=m*l;while(i++<u){e.Add((r.Next(m)-499)+a+(r.Next(m)-499));d[e[e.Count-1]]="M";}d[X]=a;while(k>0){u=x;v=y;x=k>2&&k<20?x-1:k>12?x+1:x;y=k%2>0&&k%10!=0?y-1:k%2==0&&k%10!=0?y+1:y;c=T(X);if(e.Contains(X)){e.Remove(X);d[X]=f;}R();if(c==s){d.Clear();e.Clear();new M(1,l+1,h);return;}if(c!=f){x=u;y=v;}d[u+a+v]=f;d[X]=a;for(z=0;z<e.Count;z++){i=U(e[z],0);j=U(e[z],1);u=i<x?i+1:i>x?i-1:i;v=j<y?j+1:j>y?j-1:j;c=T(u+a+v);if(c==f){e[z]=u+a+v;d[e[z]]=d[i+a+j];d[i+a+j]=f;}if(c==a)h--;}if(h<1)return;z=p*2-1;for(j=0;j<z;j++){for(i=0;i<z;i++){c=T((i-p+x)+a+(j-p+y));W(c,c==w?l:0);}L();}L(l+f+h);k=I;}}S X{get{return x+a+y;}}S T(S c){return d.ContainsKey(c)?d[c]:d[c]=r.Next(m*p)<5?s:r.Next(9)<7?f:w;}int U(S c,int l){return int.Parse((c.Split('@'))[l]);}static void Main(){new M(1,1,9);}}
using System;
using S = System.String;
using System.Collections.Generic;
partial class M {
Dictionary<S, S> d = new Dictionary<S, S>( );
List<S> e = new List<S>( );
int p = 9, m = 999, x, y, z, u, v, i, j;
S a = "@", w = "#", f = ".", s = ">", c;
Random r = new Random( );
M( int k, int l, int h ) {
//determine number of enemies
u = m * l;
//add enemies
while ( i++ < u ) {
e.Add( ( r.Next( m ) - 499 ) + a + ( r.Next( m ) - 499 ) );
d[ e[ e.Count - 1 ] ] = "M";
}
//set player start
d[ X ] = a;
//k will be 0 if player presses Q or ESC
while ( k > 0 ) {
//store player co-ords
u = x;
v = y;
//handle keyboard return code
x = k > 2 && k < 20 ? x - 1 : k > 12 ? x + 1 : x;
y = k % 2 > 0 && k % 10 != 0 ? y - 1 : k % 2 == 0 && k % 10 != 0 ? y + 1 : y;
//get the string at the new location
c = T( X );
//if player is hitting an enemy
if ( e.Contains( X ) ) {
//kill the enemy
e.Remove( X );
d[ X ] = f;
}
//reset the cursor position
R( );
//if the player is standing on stairs
if ( c == s ) {
//reset the dungeon and enemies
d.Clear( );
e.Clear( );
//new dungeon
new M( 1, l + 1, h );
//if we get here player has died, exit
return;
}
//if the player tried to move onto something that isn't a floor, put
//them back where they were
if ( c != f ) {
x = u;
y = v;
}
//set the last tile that the player was on to floor
d[ u + a + v ] = f;
//set the tile that the player is currently on to @
d[ X ] = a;
//iterate through the remaining enemies
for ( z = 0; z < e.Count; z++ ) {
//get the current enemy's location and store their X position in i and
//their Y position in j
i = U( e[ z ], 0 );
j = U( e[ z ], 1 );
//move towards the player
u = i < x ? i + 1 : i > x ? i - 1 : i;
v = j < y ? j + 1 : j > y ? j - 1 : j;
//get the dungeon tile at the new enemy coordinate
c = T( u + a + v );
//if the dungeon tile is floor, move the enemy onto the new coordinate
if ( c == f ) {
e[ z ] = u + a + v;
d[ e[ z ] ] = d[ i + a + j ];
d[ i + a + j ] = f;
}
//if the dungeon tile the enemy tried to move to contains the player,
//decrement the player's health
if ( c == a ) h--;
}
//exit if player is dead
if ( h < 1 ) return;
//calculate the viewport size using p
z = p * 2 - 1;
//draw visible dungeon tiles to viewport
for ( j = 0; j < z; j++ ) {
for ( i = 0; i < z; i++ ) {
//get tile at location X = i, Y = j
c = T( ( i - p + x ) + a + ( j - p + y ) );
//if it's a wall pass the level through to the IO call for the color,
//otherwise pass through 0 to use default color
W( c, c == w ? l : 0 );
}
L( );
}
//show level and health
L( l + f + h );
//get keyboard input
k = I;
}
}
//return the player's coordinates as a string
S X {
get { return x + a + y; }
}
//get the dungeon tile at the passed in coordinate. If the tile doesn't exist
//create it
S T( S c ) {
return d.ContainsKey( c ) ? d[ c ] : d[ c ] = r.Next( m * p ) < 5 ? s : r.Next( 9 ) < 7 ? f : w;
}
//convert a string coordinate to an x or a y coordinate - if l is 0, return
//x, if l is 1 return y
int U( S c, int l ) { return int.Parse( ( c.Split( '@' ) )[ l ] ); }
//start a new game on level 1 with 9 health
static void Main( ) { new M( 1, 1, 9 ); }
}
using System;using C=System.Console;using K=System.ConsoleKey;using O=System.ConsoleColor;partial class M{void W(string s,int c){if(c==0)C.ForegroundColor=(O)7;else{while(c>15)c-=15;C.ForegroundColor=(O)c;}C.Write(s);}void L(){L("");}void L(object o){C.ForegroundColor=(O)15;C.WriteLine(o);}void R(){C.BackgroundColor=0;C.SetCursorPosition(0,0);}static int I{get{switch((C.ReadKey(true)).Key){case K.Q:case K.Escape:return 0;case K.LeftArrow:case K.NumPad4:case K.H:return 10;case K.RightArrow:case K.NumPad6:case K.L:return 20;case K.UpArrow:case K.NumPad8:case K.K:return 1;case K.DownArrow:case K.NumPad2:case K.J:return 2;case K.NumPad7:case K.Y:return 11;case K.NumPad9:case K.U:return 21;case K.NumPad1:case K.B:return 12;case K.NumPad3:case K.N:return 22;}return 5;}}}