b6daa1efa1 2012-07-14 kinaba: import util; b6daa1efa1 2012-07-14 kinaba: import output; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: //////////////////////////////////////////////////////////////////////////////// b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: class Pos b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: public immutable int y, x; b6daa1efa1 2012-07-14 kinaba: mixin DeriveCreate; b6daa1efa1 2012-07-14 kinaba: mixin DeriveCompare; b6daa1efa1 2012-07-14 kinaba: mixin DeriveShow; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: @property: b6daa1efa1 2012-07-14 kinaba: Pos wait() { return this; } b6daa1efa1 2012-07-14 kinaba: Pos up() { return new Pos(y+1, x); } b6daa1efa1 2012-07-14 kinaba: Pos down() { return new Pos(y-1, x); } b6daa1efa1 2012-07-14 kinaba: Pos left() { return new Pos(y, x-1); } b6daa1efa1 2012-07-14 kinaba: Pos right() { return new Pos(y, x+1); } b6daa1efa1 2012-07-14 kinaba: alias wait W,w; b6daa1efa1 2012-07-14 kinaba: alias up U,u; b6daa1efa1 2012-07-14 kinaba: alias down D,d; b6daa1efa1 2012-07-14 kinaba: alias left L,l; b6daa1efa1 2012-07-14 kinaba: alias right R,r; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: unittest b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: assert( (new Pos(2,1)).U == new Pos(3,1) ); b6daa1efa1 2012-07-14 kinaba: assert( (new Pos(0,1)).D == new Pos(-1,1) ); b6daa1efa1 2012-07-14 kinaba: assert( (new Pos(2,1)).L == new Pos(2,0) ); b6daa1efa1 2012-07-14 kinaba: assert( (new Pos(2,1)).R == new Pos(2,2) ); b6daa1efa1 2012-07-14 kinaba: int[Pos] aa; b6daa1efa1 2012-07-14 kinaba: aa[new Pos(1,2)] = 1; b6daa1efa1 2012-07-14 kinaba: aa[new Pos(1,2)] = 2; b6daa1efa1 2012-07-14 kinaba: aa[new Pos(2,1)] = 3; b6daa1efa1 2012-07-14 kinaba: assert( aa.length==2 ); b6daa1efa1 2012-07-14 kinaba: assert( aa[new Pos(1,2)]==2 ); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: //////////////////////////////////////////////////////////////////////////////// b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: class Water b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: public immutable int base, pace; b6daa1efa1 2012-07-14 kinaba: mixin DeriveCreate; b6daa1efa1 2012-07-14 kinaba: mixin DeriveCompare; b6daa1efa1 2012-07-14 kinaba: mixin DeriveShow; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: static load(string[string] params) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: return new Water( b6daa1efa1 2012-07-14 kinaba: params.get("Water", "0").to!int(), b6daa1efa1 2012-07-14 kinaba: params.get("Flooding", "0").to!int() b6daa1efa1 2012-07-14 kinaba: ); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: int level(int number_of_update) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: return pace ? base+(number_of_update/pace) : base; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: int until_rise(int number_of_update) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: return pace ? pace-number_of_update%pace : int.max; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: unittest b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: Water w = new Water(1, 3); b6daa1efa1 2012-07-14 kinaba: assert( 1 == w.level(0) ); b6daa1efa1 2012-07-14 kinaba: assert( 1 == w.level(1) ); b6daa1efa1 2012-07-14 kinaba: assert( 1 == w.level(2) ); b6daa1efa1 2012-07-14 kinaba: assert( 2 == w.level(3) ); b6daa1efa1 2012-07-14 kinaba: assert( 2 == w.level(4) ); b6daa1efa1 2012-07-14 kinaba: assert( 2 == w.level(5) ); b6daa1efa1 2012-07-14 kinaba: assert( 3 == w.level(6) ); b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: w = new Water(1, 0); b6daa1efa1 2012-07-14 kinaba: assert( 1 == w.level(0) ); b6daa1efa1 2012-07-14 kinaba: assert( 1 == w.level(1) ); b6daa1efa1 2012-07-14 kinaba: assert( 1 == w.level(2) ); b6daa1efa1 2012-07-14 kinaba: assert( 1 == w.level(3) ); b6daa1efa1 2012-07-14 kinaba: assert( 1 == w.level(4) ); b6daa1efa1 2012-07-14 kinaba: assert( 1 == w.level(5) ); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: //////////////////////////////////////////////////////////////////////////////// b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: class Map b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: mixin DeriveShow; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: static Map load(string[] raw_data, string[string] params) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: // TODO: choose optimal representation. b6daa1efa1 2012-07-14 kinaba: return new Map(raw_data, params); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: private { b6daa1efa1 2012-07-14 kinaba: char[][] data; b6daa1efa1 2012-07-14 kinaba: Pos robot; b6daa1efa1 2012-07-14 kinaba: Pos lift; b6daa1efa1 2012-07-14 kinaba: int waterproof; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: this(string[] raw_data, string[string] params) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: int width = 0; b6daa1efa1 2012-07-14 kinaba: foreach(r; raw_data) b6daa1efa1 2012-07-14 kinaba: width = max(width, r.length); b6daa1efa1 2012-07-14 kinaba: foreach(r; raw_data) { b6daa1efa1 2012-07-14 kinaba: this.data ~= r.dup; b6daa1efa1 2012-07-14 kinaba: this.data[$-1].length = width; b6daa1efa1 2012-07-14 kinaba: this.data[$-1][r.length..$] = ' '; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: for(int y=1; y<=H; ++y) b6daa1efa1 2012-07-14 kinaba: for(int x=1; x<=W; ++x) { b6daa1efa1 2012-07-14 kinaba: if(this[y,x] == 'R') b6daa1efa1 2012-07-14 kinaba: this.robot = new Pos(y,x); b6daa1efa1 2012-07-14 kinaba: if(this[y,x] == 'L') b6daa1efa1 2012-07-14 kinaba: this.lift = new Pos(y,x); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: this.waterproof = params.get("Waterproof", "5").to!int(); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: const @property { b6daa1efa1 2012-07-14 kinaba: int H() { return data.length; } b6daa1efa1 2012-07-14 kinaba: int W() { return data[0].length; } b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: char opIndex(int y, int x) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: // Adjust coordinate to the spec. bottom-left is (1,1). b6daa1efa1 2012-07-14 kinaba: --y, --x; b6daa1efa1 2012-07-14 kinaba: if(y<0||H<=y||x<0||W<=x) b6daa1efa1 2012-07-14 kinaba: return '#'; b6daa1efa1 2012-07-14 kinaba: return data[H-1-y][x]; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: char opIndex(Pos p) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: return this[p.y, p.x]; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: void opIndexAssign(char c, int y, int x) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: // Adjust coordinate to the spec. bottom-left is (1,1). b6daa1efa1 2012-07-14 kinaba: --y, --x; b6daa1efa1 2012-07-14 kinaba: if(y<0||H<=y||x<0||W<=x) b6daa1efa1 2012-07-14 kinaba: return; b6daa1efa1 2012-07-14 kinaba: data[H-1-y][x] = c; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: void opIndexAssign(char c, Pos p) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: this[p.y, p.x] = c; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: bool cleared() b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: for(int y=1; y<=H; ++y) b6daa1efa1 2012-07-14 kinaba: for(int x=1; x<=W; ++x) b6daa1efa1 2012-07-14 kinaba: if(this[y,x] == 'L' || this[y,x] == 'O') b6daa1efa1 2012-07-14 kinaba: return false; b6daa1efa1 2012-07-14 kinaba: return true; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: Tuple!(int,bool) command(char c) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: if(c=='R') return move( 0, +1); b6daa1efa1 2012-07-14 kinaba: if(c=='L') return move( 0, -1); b6daa1efa1 2012-07-14 kinaba: if(c=='U') return move(+1, 0); b6daa1efa1 2012-07-14 kinaba: if(c=='D') return move(-1, 0); b6daa1efa1 2012-07-14 kinaba: if(c=='W') return move( 0, 0); b6daa1efa1 2012-07-14 kinaba: assert(false); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: Tuple!(int, bool) move(int dy, int dx) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: int y = robot.y; b6daa1efa1 2012-07-14 kinaba: int x = robot.x; b6daa1efa1 2012-07-14 kinaba: assert( this[robot] == 'R' ); b6daa1efa1 2012-07-14 kinaba: int lambda = 0; b6daa1efa1 2012-07-14 kinaba: bool dead = false; b6daa1efa1 2012-07-14 kinaba: if( '\\' == this[y+dy,x+dx] ) b6daa1efa1 2012-07-14 kinaba: lambda++; b6daa1efa1 2012-07-14 kinaba: if( " \\.O".count(this[y+dy,x+dx])==1 ) { b6daa1efa1 2012-07-14 kinaba: this[y,x]=' '; b6daa1efa1 2012-07-14 kinaba: this[y+dy,x+dx]='R'; b6daa1efa1 2012-07-14 kinaba: robot = new Pos(y+dy,x+dx); b6daa1efa1 2012-07-14 kinaba: } else if(dy==0 && '*'==this[y+dy,x+dx] && ' '==this[y+dy*2,x+dx*2]) { b6daa1efa1 2012-07-14 kinaba: this[y,x]=' '; b6daa1efa1 2012-07-14 kinaba: this[y+dy,x+dx]='R'; b6daa1efa1 2012-07-14 kinaba: this[y+dy*2,x+dx*2]='*'; b6daa1efa1 2012-07-14 kinaba: robot = new Pos(y+dy,x+dx); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: if( update() ) b6daa1efa1 2012-07-14 kinaba: dead = true; b6daa1efa1 2012-07-14 kinaba: return tuple(lambda,dead); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: bool update() b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: bool dead = false; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: char[][] next; b6daa1efa1 2012-07-14 kinaba: foreach(y,s; data) b6daa1efa1 2012-07-14 kinaba: next ~= s.dup; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: ref char access(Pos p) { return next[H-p.y][p.x-1]; } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: bool lambda = false; b6daa1efa1 2012-07-14 kinaba: for(int y=1; y<=H; ++y) b6daa1efa1 2012-07-14 kinaba: for(int x=1; x<=W; ++x) b6daa1efa1 2012-07-14 kinaba: lambda |= (this[y,x] == '\\'); b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: for(int y=1; y<=H; ++y) b6daa1efa1 2012-07-14 kinaba: for(int x=1; x<=W; ++x) { b6daa1efa1 2012-07-14 kinaba: Pos p = new Pos(y,x); b6daa1efa1 2012-07-14 kinaba: if(this[p]=='*') { b6daa1efa1 2012-07-14 kinaba: if(this[p.D]==' ') { b6daa1efa1 2012-07-14 kinaba: access(p) =' '; b6daa1efa1 2012-07-14 kinaba: access(p.D)='*'; b6daa1efa1 2012-07-14 kinaba: if(robot == p.D.D) b6daa1efa1 2012-07-14 kinaba: dead=true; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: else if((this[p.D]=='*' || this[p.D]=='\\') && this[p.R]==' ' && this[p.R.D]==' ') { b6daa1efa1 2012-07-14 kinaba: access(p)=' '; b6daa1efa1 2012-07-14 kinaba: access(p.R.D)='*'; b6daa1efa1 2012-07-14 kinaba: if(robot == p.R.D.D) b6daa1efa1 2012-07-14 kinaba: dead=true; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: else if(this[p.D]=='*' && this[p.L]==' ' && this[p.L.D]==' ') { b6daa1efa1 2012-07-14 kinaba: access(p)=' '; b6daa1efa1 2012-07-14 kinaba: access(p.L.D)='*'; b6daa1efa1 2012-07-14 kinaba: if(robot == p.L.D.D) b6daa1efa1 2012-07-14 kinaba: dead=true; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: else if(this[p]=='L') { b6daa1efa1 2012-07-14 kinaba: if(!lambda) b6daa1efa1 2012-07-14 kinaba: access(p) = 'O'; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: data = next; b6daa1efa1 2012-07-14 kinaba: return dead; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: //////////////////////////////////////////////////////////////////////////////// b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: class Game b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: mixin DeriveShow; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: static Game load(File input) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: string[] raw_data; b6daa1efa1 2012-07-14 kinaba: string[string] params; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: // Raw map data; read until empty line. b6daa1efa1 2012-07-14 kinaba: for(string line; !(line=input.readln().chomp()).empty; ) b6daa1efa1 2012-07-14 kinaba: raw_data ~= line; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: // Additional commands; read until EOF. b6daa1efa1 2012-07-14 kinaba: for(string line; !(line=input.readln()).empty; ) { b6daa1efa1 2012-07-14 kinaba: string[] ss = line.split(); b6daa1efa1 2012-07-14 kinaba: if( ss.length == 2 ) b6daa1efa1 2012-07-14 kinaba: params[ss[0]] = ss[1]; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: return load(raw_data, params); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: static Game load(string[] raw_data, string[string] params) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: return new Game(raw_data, params); b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: this(string[] raw_data, string[string] params) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: this.map = Map.load(raw_data, params); b6daa1efa1 2012-07-14 kinaba: this.water = Water.load(params); b6daa1efa1 2012-07-14 kinaba: this.output = new NilOutput; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: void set_output(Output o) { this.output = (o is null ? new NilOutput : o); } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: void command(char c) b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: if(dead || cleared) b6daa1efa1 2012-07-14 kinaba: return; b6daa1efa1 2012-07-14 kinaba: this.output.command(c); b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: if(c == 'A') b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: exit_bonus = 1; b6daa1efa1 2012-07-14 kinaba: return; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: // TODO: clarify the event order b6daa1efa1 2012-07-14 kinaba: Tuple!(int,bool) ld = map.command(c); b6daa1efa1 2012-07-14 kinaba: if( map.cleared() ) { b6daa1efa1 2012-07-14 kinaba: exit_bonus = 2; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: else { b6daa1efa1 2012-07-14 kinaba: lambda += ld[0]; b6daa1efa1 2012-07-14 kinaba: if( ld[1] ) { b6daa1efa1 2012-07-14 kinaba: dead = true; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: if( map.robot.y <= water_level ) b6daa1efa1 2012-07-14 kinaba: ++under_warter; b6daa1efa1 2012-07-14 kinaba: else b6daa1efa1 2012-07-14 kinaba: under_warter = 0; b6daa1efa1 2012-07-14 kinaba: if( under_warter > map.waterproof ) b6daa1efa1 2012-07-14 kinaba: dead = true; b6daa1efa1 2012-07-14 kinaba: turn += 1; b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: Map map; b6daa1efa1 2012-07-14 kinaba: Water water; b6daa1efa1 2012-07-14 kinaba: Output output; b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: int turn = 0; b6daa1efa1 2012-07-14 kinaba: bool dead = false; b6daa1efa1 2012-07-14 kinaba: int lambda = 0; b6daa1efa1 2012-07-14 kinaba: int exit_bonus = 0; b6daa1efa1 2012-07-14 kinaba: int under_warter = 0; b6daa1efa1 2012-07-14 kinaba: @property { 3e342af26c 2012-07-14 kinaba: long score() { return lambda*25L*(1+exit_bonus) - turn; } b6daa1efa1 2012-07-14 kinaba: int water_level() { return water.level(turn); } b6daa1efa1 2012-07-14 kinaba: int water_until_rise() { return water.until_rise(turn); } b6daa1efa1 2012-07-14 kinaba: bool cleared() { return exit_bonus>0; } b6daa1efa1 2012-07-14 kinaba: int hp() { return map.waterproof - under_warter; } 3e342af26c 2012-07-14 kinaba: long score_if_abort_now() { return lambda*25*(1+max(1,exit_bonus)) - turn; } b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: } b6daa1efa1 2012-07-14 kinaba: b6daa1efa1 2012-07-14 kinaba: unittest b6daa1efa1 2012-07-14 kinaba: { b6daa1efa1 2012-07-14 kinaba: Game.load(["###","...","#RL"], ["xxx":"yyy"]); b6daa1efa1 2012-07-14 kinaba: }