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