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: b1ce0206cd 2012-07-14 kinaba: static load(string[string] params) 6293256fec 2012-07-14 kinaba: { 4aa9d7f484 2012-07-15 kinaba: return new Water(params.get("Water", "0").to!int(), 4aa9d7f484 2012-07-15 kinaba: params.get("Flooding", "0").to!int()); 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: 9d983af88c 2012-07-15 kinaba: class Hige 9d983af88c 2012-07-15 kinaba: { 9d983af88c 2012-07-15 kinaba: public immutable int pace; 9d983af88c 2012-07-15 kinaba: mixin DeriveCreate; 9d983af88c 2012-07-15 kinaba: mixin DeriveCompare; 9d983af88c 2012-07-15 kinaba: mixin DeriveShow; 9d983af88c 2012-07-15 kinaba: Hige clone() const { return cast(Hige)this; } 9d983af88c 2012-07-15 kinaba: 9d983af88c 2012-07-15 kinaba: static load(string[string] params) 9d983af88c 2012-07-15 kinaba: { 9d983af88c 2012-07-15 kinaba: return new Hige(params.get("Growth", "25").to!int()); 9d983af88c 2012-07-15 kinaba: } 9d983af88c 2012-07-15 kinaba: 9d983af88c 2012-07-15 kinaba: bool is_growing_turn(int turn) const 9d983af88c 2012-07-15 kinaba: { 9d983af88c 2012-07-15 kinaba: return pace ? turn%pace == pace-1 : false; 9d983af88c 2012-07-15 kinaba: } 9d983af88c 2012-07-15 kinaba: 9d983af88c 2012-07-15 kinaba: int until_rise(int turn) const 9d983af88c 2012-07-15 kinaba: { 9d983af88c 2012-07-15 kinaba: return pace ? pace-turn%pace : int.max; 9d983af88c 2012-07-15 kinaba: } 9d983af88c 2012-07-15 kinaba: } 9d983af88c 2012-07-15 kinaba: 9d983af88c 2012-07-15 kinaba: //////////////////////////////////////////////////////////////////////////////// 9d983af88c 2012-07-15 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: b8acb5f918 2012-07-14 kinaba: static Map load(string[] raw_data, string[string] params, char[char] trampo) 6293256fec 2012-07-14 kinaba: { 6293256fec 2012-07-14 kinaba: // TODO: choose optimal representation. b8acb5f918 2012-07-14 kinaba: return new Map(raw_data, params, trampo); 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; b8acb5f918 2012-07-14 kinaba: Pos[char] tr_target; b8acb5f918 2012-07-14 kinaba: Pos[][char] tr_source; 9d983af88c 2012-07-15 kinaba: const(Hige) hige; 9d983af88c 2012-07-15 kinaba: int razor; 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; deca17f61a 2012-07-14 kinaba: this.tr_target = cast(Pos[char])m.tr_target; deca17f61a 2012-07-14 kinaba: this.tr_source = cast(Pos[][char])m.tr_source; 9d983af88c 2012-07-15 kinaba: this.hige = m.hige.clone(); 9d983af88c 2012-07-15 kinaba: this.razor = m.razor; 6293256fec 2012-07-14 kinaba: } 6293256fec 2012-07-14 kinaba: b8acb5f918 2012-07-14 kinaba: this(string[] raw_data, string[string] params, char[char] trampo) 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: b8acb5f918 2012-07-14 kinaba: Pos[char] tr_pos; b8acb5f918 2012-07-14 kinaba: for(int y=1; y<=H; ++y) b8acb5f918 2012-07-14 kinaba: for(int x=1; x<=W; ++x) { b8acb5f918 2012-07-14 kinaba: char c = this[y,x]; b8acb5f918 2012-07-14 kinaba: if('1'<=c && c<='9' || 'A'<=c&&c<='I') b8acb5f918 2012-07-14 kinaba: tr_pos[c] = new Pos(y,x); b8acb5f918 2012-07-14 kinaba: } b8acb5f918 2012-07-14 kinaba: b1ce0206cd 2012-07-14 kinaba: this.waterproof = params.get("Waterproof", "5").to!int(); b8acb5f918 2012-07-14 kinaba: foreach(fr,to; trampo) { b8acb5f918 2012-07-14 kinaba: tr_target[fr] = tr_pos[to]; b8acb5f918 2012-07-14 kinaba: if(to !in tr_source) tr_source[to] = []; deca17f61a 2012-07-14 kinaba: tr_source[to] ~= tr_pos[fr]; b8acb5f918 2012-07-14 kinaba: } 9d983af88c 2012-07-15 kinaba: 9d983af88c 2012-07-15 kinaba: this.hige = Hige.load(params); 9d983af88c 2012-07-15 kinaba: this.razor = params.get("Razors", "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: 34bbd14c1a 2012-07-15 kinaba: Pos[] objects(char c) 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) 34bbd14c1a 2012-07-15 kinaba: if(this[y,x] == c) 6293256fec 2012-07-14 kinaba: ans ~= new Pos(y,x); 6293256fec 2012-07-14 kinaba: return ans; 6293256fec 2012-07-14 kinaba: } 34bbd14c1a 2012-07-15 kinaba: 34bbd14c1a 2012-07-15 kinaba: Pos[] razors() const { return objects('!'); } 34bbd14c1a 2012-07-15 kinaba: Pos[] lambdas() const { return objects('\\'); } 9d4aca73fa 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: 2b4f8bba2d 2012-07-15 kinaba: Tuple!(int,bool) command(char c, int turn) 6293256fec 2012-07-14 kinaba: { 3a08e528e7 2012-07-15 kinaba: assert( this[robot] == 'R' ); 2b4f8bba2d 2012-07-15 kinaba: if(c=='R') return move( 0, +1, turn); 2b4f8bba2d 2012-07-15 kinaba: if(c=='L') return move( 0, -1, turn); 2b4f8bba2d 2012-07-15 kinaba: if(c=='U') return move(+1, 0, turn); 2b4f8bba2d 2012-07-15 kinaba: if(c=='D') return move(-1, 0, turn); 2b4f8bba2d 2012-07-15 kinaba: if(c=='W') return move( 0, 0, turn); 3a08e528e7 2012-07-15 kinaba: if(c=='S') return use_razor(turn); 6293256fec 2012-07-14 kinaba: assert(false); 3a08e528e7 2012-07-15 kinaba: } 3a08e528e7 2012-07-15 kinaba: 3a08e528e7 2012-07-15 kinaba: Tuple!(int, bool) use_razor(int turn) 3a08e528e7 2012-07-15 kinaba: { 3a08e528e7 2012-07-15 kinaba: if(razor) { 3a08e528e7 2012-07-15 kinaba: razor--; 3a08e528e7 2012-07-15 kinaba: for(int dy=-1; dy<=+1; ++dy) 3a08e528e7 2012-07-15 kinaba: for(int dx=-1; dx<=+1; ++dx) 3a08e528e7 2012-07-15 kinaba: if(this[robot.y+dy,robot.x+dx] == 'W') 3a08e528e7 2012-07-15 kinaba: this[robot.y+dy,robot.x+dx] = ' '; 3a08e528e7 2012-07-15 kinaba: } 3a08e528e7 2012-07-15 kinaba: 3a08e528e7 2012-07-15 kinaba: bool dead = update(turn); 3a08e528e7 2012-07-15 kinaba: return tuple(0,dead); 2b4f8bba2d 2012-07-15 kinaba: } 2b4f8bba2d 2012-07-15 kinaba: 2b4f8bba2d 2012-07-15 kinaba: Tuple!(int, bool) move(int dy, int dx, int turn) 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: int lambda = 0; 6293256fec 2012-07-14 kinaba: if( '\\' == this[y+dy,x+dx] ) 6293256fec 2012-07-14 kinaba: lambda++; 41c73506fb 2012-07-15 kinaba: if( '!' == this[y+dy,x+dx] ) 41c73506fb 2012-07-15 kinaba: razor++; 41c73506fb 2012-07-15 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); deca17f61a 2012-07-14 kinaba: } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') { deca17f61a 2012-07-14 kinaba: this[y,x]=' '; deca17f61a 2012-07-14 kinaba: Pos tp = tr_target[this[y+dy,x+dx]]; deca17f61a 2012-07-14 kinaba: foreach(p; tr_source[this[tp]]) deca17f61a 2012-07-14 kinaba: this[p] = ' '; deca17f61a 2012-07-14 kinaba: this[tp] = 'R'; deca17f61a 2012-07-14 kinaba: robot = tp; 6293256fec 2012-07-14 kinaba: } 3a08e528e7 2012-07-15 kinaba: bool dead = update(turn); 6293256fec 2012-07-14 kinaba: return tuple(lambda,dead); 6293256fec 2012-07-14 kinaba: } 6293256fec 2012-07-14 kinaba: 2b4f8bba2d 2012-07-15 kinaba: bool update(int turn) 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: } 2b4f8bba2d 2012-07-15 kinaba: else if(this[p]=='W') { 2b4f8bba2d 2012-07-15 kinaba: if( hige.is_growing_turn(turn) ) 2b4f8bba2d 2012-07-15 kinaba: for(int dy=-1; dy<=+1; ++dy) 2b4f8bba2d 2012-07-15 kinaba: for(int dx=-1; dx<=+1; ++dx) 2b4f8bba2d 2012-07-15 kinaba: if(this[p.y+dy,p.x+dx] == ' ') 2b4f8bba2d 2012-07-15 kinaba: access(new Pos(p.y+dy,p.x+dx)) = 'W'; 2b4f8bba2d 2012-07-15 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: //////////////////////////////////////////////////////////////////////////////// ff0ab77d3d 2012-07-15 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: { b1ce0206cd 2012-07-14 kinaba: string[] raw_data; b1ce0206cd 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. b8acb5f918 2012-07-14 kinaba: char[char] trampo; 6293256fec 2012-07-14 kinaba: for(string line; !(line=input.readln()).empty; ) { 6293256fec 2012-07-14 kinaba: string[] ss = line.split(); b1ce0206cd 2012-07-14 kinaba: if( ss.length == 2 ) b1ce0206cd 2012-07-14 kinaba: params[ss[0]] = ss[1]; b8acb5f918 2012-07-14 kinaba: if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="targets" ) b8acb5f918 2012-07-14 kinaba: trampo[ss[1][0]] = ss[3][0]; 6293256fec 2012-07-14 kinaba: } 6293256fec 2012-07-14 kinaba: b8acb5f918 2012-07-14 kinaba: return load(raw_data, params, trampo); 6293256fec 2012-07-14 kinaba: } 6293256fec 2012-07-14 kinaba: b8acb5f918 2012-07-14 kinaba: static Game load(string[] raw_data, string[string] params, char[char] trampo = null) 6293256fec 2012-07-14 kinaba: { b8acb5f918 2012-07-14 kinaba: return new Game(raw_data, params, trampo); 6293256fec 2012-07-14 kinaba: } 6293256fec 2012-07-14 kinaba: b8acb5f918 2012-07-14 kinaba: this(string[] raw_data, string[string] params, char[char] trampo) 6293256fec 2012-07-14 kinaba: { b8acb5f918 2012-07-14 kinaba: this.map = Map.load(raw_data, params, trampo); 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; 879099f815 2012-07-15 kinaba: cleared = g.cleared; 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: { 879099f815 2012-07-15 kinaba: assert(c != 'A'); 6293256fec 2012-07-14 kinaba: if(dead || cleared) 6293256fec 2012-07-14 kinaba: return; 6293256fec 2012-07-14 kinaba: 6293256fec 2012-07-14 kinaba: // TODO: clarify the event order 2b4f8bba2d 2012-07-15 kinaba: Tuple!(int,bool) ld = map.command(c, turn); 6293256fec 2012-07-14 kinaba: if( map.cleared() ) { 879099f815 2012-07-15 kinaba: cleared = true; 6293256fec 2012-07-14 kinaba: } 6293256fec 2012-07-14 kinaba: else { 6293256fec 2012-07-14 kinaba: lambda += ld[0]; 879099f815 2012-07-15 kinaba: if( ld[1] ) 879099f815 2012-07-15 kinaba: dead = true; 879099f815 2012-07-15 kinaba: } 6d497011d6 2012-07-15 kinaba: if(!cleared) { 6d497011d6 2012-07-15 kinaba: if( map.robot.y <= water_level ) 6d497011d6 2012-07-15 kinaba: ++under_water; 6d497011d6 2012-07-15 kinaba: else 6d497011d6 2012-07-15 kinaba: under_water = 0; 6d497011d6 2012-07-15 kinaba: if( under_water > map.waterproof ) 6d497011d6 2012-07-15 kinaba: dead = true; 6d497011d6 2012-07-15 kinaba: } 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 under_water = 0; 879099f815 2012-07-15 kinaba: bool cleared = false; 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 { 879099f815 2012-07-15 kinaba: long score() { return lambda*(dead ? 25L : cleared ? 75L : 50L) - 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); } 9d983af88c 2012-07-15 kinaba: int hige_until_rise() { return map.hige.until_rise(turn); } 6293256fec 2012-07-14 kinaba: int hp() { return map.waterproof - under_water; } 879099f815 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: */ ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: //////////////////////////////////////////////////////////////////////////////// ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: class Game ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: public: ff0ab77d3d 2012-07-15 kinaba: this(File input) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: // Read map data ff0ab77d3d 2012-07-15 kinaba: string[] map_data_lines; ff0ab77d3d 2012-07-15 kinaba: for(string line; !(line=input.readln().chomp()).empty; ) ff0ab77d3d 2012-07-15 kinaba: map_data_lines ~= line; ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: // H*W ff0ab77d3d 2012-07-15 kinaba: H_ = map_data_lines.length; ff0ab77d3d 2012-07-15 kinaba: W_ = 0; ff0ab77d3d 2012-07-15 kinaba: foreach(mdl; map_data_lines) ff0ab77d3d 2012-07-15 kinaba: W_ = max(W_, mdl.length); ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: // Copy to modifiable buffer and adjust coordinates. ff0ab77d3d 2012-07-15 kinaba: raw_data_ = new char[][H_+1]; ff0ab77d3d 2012-07-15 kinaba: foreach(i,mdl; map_data_lines) { ff0ab77d3d 2012-07-15 kinaba: char[] buf = new char[mdl.length+1]; ff0ab77d3d 2012-07-15 kinaba: buf[0] = '#'; ff0ab77d3d 2012-07-15 kinaba: buf[1..$] = mdl[]; ff0ab77d3d 2012-07-15 kinaba: raw_data_[H_-i] = buf; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: // Detect objects ff0ab77d3d 2012-07-15 kinaba: for(int y=1; y<=H_; ++y) ff0ab77d3d 2012-07-15 kinaba: for(int x=1; x<raw_data_[y].length; ++x) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: char c = raw_data_[y][x]; ff0ab77d3d 2012-07-15 kinaba: switch(c) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: case '#': ff0ab77d3d 2012-07-15 kinaba: case '.': ff0ab77d3d 2012-07-15 kinaba: case ' ': ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case 'L': ff0ab77d3d 2012-07-15 kinaba: case 'O': ff0ab77d3d 2012-07-15 kinaba: lift_pos_ = new Pos(y,x); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case 'A': .. case 'I': ff0ab77d3d 2012-07-15 kinaba: case '1': .. case '9': ff0ab77d3d 2012-07-15 kinaba: trampoline_pos_[c] = new Pos(y,x); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case '!': ff0ab77d3d 2012-07-15 kinaba: razor_pos_ ~= new Pos(y,x); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case '\\': ff0ab77d3d 2012-07-15 kinaba: lambda_pos_ ~= new Pos(y,x); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: // Moving objects are erased from raw_data_ ff0ab77d3d 2012-07-15 kinaba: case 'R': ff0ab77d3d 2012-07-15 kinaba: robot_pos_ = new Pos(y,x); ff0ab77d3d 2012-07-15 kinaba: raw_data_[y][x] = ' '; ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case '*': ff0ab77d3d 2012-07-15 kinaba: case 'W': ff0ab77d3d 2012-07-15 kinaba: dynamic_objects_[new Pos(y,x)] = c; ff0ab77d3d 2012-07-15 kinaba: raw_data_[y][x] = ' '; ff0ab77d3d 2012-07-15 kinaba: if(c=='*') ff0ab77d3d 2012-07-15 kinaba: may_update_[new Pos(y,x)] = true; ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: default: ff0ab77d3d 2012-07-15 kinaba: assert(false); ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: // Read other parameters ff0ab77d3d 2012-07-15 kinaba: for(string line; !(line=input.readln()).empty; ) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: string[] ss = line.split(); ff0ab77d3d 2012-07-15 kinaba: if( ss.length == 2 ) ff0ab77d3d 2012-07-15 kinaba: switch(ss[0]) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: case "Water": water_base_ = ss[1].to!int(); break; ff0ab77d3d 2012-07-15 kinaba: case "Flooding": water_pace_ = ss[1].to!int(); break; ff0ab77d3d 2012-07-15 kinaba: case "Waterproof": max_air_ = ss[1].to!int(); break; ff0ab77d3d 2012-07-15 kinaba: case "Growth": hige_pace_ = ss[1].to!int(); break; ff0ab77d3d 2012-07-15 kinaba: case "Razors": num_razor_ = ss[1].to!int(); break; ff0ab77d3d 2012-07-15 kinaba: default: assert(false); ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="targets" ) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: char fr=ss[1][0], to=ss[3][0]; ff0ab77d3d 2012-07-15 kinaba: trampoline_[fr] = to; ff0ab77d3d 2012-07-15 kinaba: if(to !in trampoline_rev_) trampoline_rev_[to] = []; ff0ab77d3d 2012-07-15 kinaba: trampoline_rev_[to] ~= fr; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: air_left_ = max_air_; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: @property const { ff0ab77d3d 2012-07-15 kinaba: int H() { return H_; } ff0ab77d3d 2012-07-15 kinaba: int W() { return W_; } ff0ab77d3d 2012-07-15 kinaba: char trampoline(char c) { return (c in trampoline_ ? trampoline_[c] : 0); } ff0ab77d3d 2012-07-15 kinaba: int water_level() { ff0ab77d3d 2012-07-15 kinaba: return water_pace_ ? water_base_ + turn_/water_pace_ : water_base_; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: int water_until_rise() { ff0ab77d3d 2012-07-15 kinaba: return water_pace_ ? water_pace_ - turn_%water_pace_ : int.max; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: int hige_until_rise() { ff0ab77d3d 2012-07-15 kinaba: return hige_pace_ ? hige_pace_ - turn_%hige_pace_ : int.max; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: bool is_hige_turn() { ff0ab77d3d 2012-07-15 kinaba: return hige_pace_ ? turn_%hige_pace_ == hige_pace_-1 : false; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: int hp() { return air_left_; } ff0ab77d3d 2012-07-15 kinaba: int num_razor() { return num_razor_; } ff0ab77d3d 2012-07-15 kinaba: bool cleared() { return cleared_; } ff0ab77d3d 2012-07-15 kinaba: bool dead() { return dead_; } ff0ab77d3d 2012-07-15 kinaba: long score() { return num_lambda_*(dead_ ? 25L : cleared_ ? 75L : 50L) - turn_; } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: const { ff0ab77d3d 2012-07-15 kinaba: char opIndex(in Pos p) { return opIndex(p.y, p.x); } ff0ab77d3d 2012-07-15 kinaba: char opIndex(int y, int x) { return map_get(y, x); } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: public: ff0ab77d3d 2012-07-15 kinaba: void command(char c) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: if(dead || cleared) ff0ab77d3d 2012-07-15 kinaba: return; ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: if(c == 'U') command_move(+1, 0); ff0ab77d3d 2012-07-15 kinaba: if(c == 'D') command_move(-1, 0); ff0ab77d3d 2012-07-15 kinaba: if(c == 'L') command_move(0, -1); ff0ab77d3d 2012-07-15 kinaba: if(c == 'R') command_move(0, +1); ff0ab77d3d 2012-07-15 kinaba: if(c == 'S') use_razor(); ff0ab77d3d 2012-07-15 kinaba: if(c == 'W') {} ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: if(cleared) ff0ab77d3d 2012-07-15 kinaba: return; ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: map_update(); ff0ab77d3d 2012-07-15 kinaba: water_update(); ff0ab77d3d 2012-07-15 kinaba: turn_ ++; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void command_move(int dy, int dx) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: int y = robot_pos_.y, x = robot_pos_.x; ff0ab77d3d 2012-07-15 kinaba: char c = this[y+dy, x+dx]; ff0ab77d3d 2012-07-15 kinaba: Pos p = new Pos(y+dy, x+dx); ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: switch(c){ ff0ab77d3d 2012-07-15 kinaba: case 'O': ff0ab77d3d 2012-07-15 kinaba: cleared_ = true; ff0ab77d3d 2012-07-15 kinaba: move_robot_to(p); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case '\\': ff0ab77d3d 2012-07-15 kinaba: take_lambda_at(p); ff0ab77d3d 2012-07-15 kinaba: move_robot_to(p); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case '!': ff0ab77d3d 2012-07-15 kinaba: take_razor_at(p); ff0ab77d3d 2012-07-15 kinaba: move_robot_to(p); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case 'A': .. case 'I': ff0ab77d3d 2012-07-15 kinaba: enter_trampoline_at(p, c); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case ' ': ff0ab77d3d 2012-07-15 kinaba: case '.': ff0ab77d3d 2012-07-15 kinaba: move_robot_to(p); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: case '*': ff0ab77d3d 2012-07-15 kinaba: if(dy!=0 || this[y,x+dx*2]!=' ') ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: move_robot_to(p); ff0ab77d3d 2012-07-15 kinaba: push_rock(p, new Pos(y,x+dx*2)); ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: default: ff0ab77d3d 2012-07-15 kinaba: break; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void use_razor() ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: if(num_razor_ == 0) ff0ab77d3d 2012-07-15 kinaba: return; ff0ab77d3d 2012-07-15 kinaba: num_razor_ --; ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: for(int dy=-1; dy<=+1; ++dy) ff0ab77d3d 2012-07-15 kinaba: for(int dx=-1; dx<=+1; ++dx) if(dy||dx) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: Pos p = new Pos(robot_pos_.y+dy, robot_pos_.x+dx); ff0ab77d3d 2012-07-15 kinaba: if(auto it = p in dynamic_objects_) ff0ab77d3d 2012-07-15 kinaba: if(*it == 'W') { ff0ab77d3d 2012-07-15 kinaba: something_gone(p); ff0ab77d3d 2012-07-15 kinaba: dynamic_objects_.remove(p); ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void take_lambda_at(Pos p) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: map_set_empty(p); ff0ab77d3d 2012-07-15 kinaba: num_lambda_ ++; ff0ab77d3d 2012-07-15 kinaba: lambda_pos_ = lambda_pos_.erase(p); ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void take_razor_at(Pos p) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: map_set_empty(p); ff0ab77d3d 2012-07-15 kinaba: num_razor_ ++; ff0ab77d3d 2012-07-15 kinaba: razor_pos_ = razor_pos_.erase(p); ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void enter_trampoline_at(Pos p, char c) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: char d = trampoline(c); ff0ab77d3d 2012-07-15 kinaba: foreach(cc; trampoline_rev_[d]) { ff0ab77d3d 2012-07-15 kinaba: Pos pp = trampoline_pos_[cc]; ff0ab77d3d 2012-07-15 kinaba: something_gone(pp); ff0ab77d3d 2012-07-15 kinaba: map_set_empty(pp); ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: move_robot_to(trampoline_pos_[d]); ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void move_robot_to(Pos p) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: something_gone(robot_pos_); ff0ab77d3d 2012-07-15 kinaba: map_set_empty(p.y, p.x); ff0ab77d3d 2012-07-15 kinaba: robot_pos_ = p; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void push_rock(Pos fr, Pos to) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: dynamic_objects_.remove(fr); ff0ab77d3d 2012-07-15 kinaba: dynamic_objects_[to] = '*'; ff0ab77d3d 2012-07-15 kinaba: may_update_[to] = true; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void something_gone(Pos p) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: for(int dy=0; dy<=+1; ++dy) ff0ab77d3d 2012-07-15 kinaba: for(int dx=-1; dx<=+1; ++dx) if(dy||dx) ff0ab77d3d 2012-07-15 kinaba: may_update_[new Pos(p.y+dy,p.x+dx)] = true; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void map_update() ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: Pos[] may_update_list; ff0ab77d3d 2012-07-15 kinaba: foreach(p,_; may_update_) ff0ab77d3d 2012-07-15 kinaba: if(this[p] == '*') ff0ab77d3d 2012-07-15 kinaba: may_update_list ~= p; ff0ab77d3d 2012-07-15 kinaba: may_update_ = null; ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: if( is_hige_turn() ) ff0ab77d3d 2012-07-15 kinaba: foreach(p,c; dynamic_objects_) ff0ab77d3d 2012-07-15 kinaba: if(c == 'W') ff0ab77d3d 2012-07-15 kinaba: may_update_list ~= p; ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: sort(may_update_list); ff0ab77d3d 2012-07-15 kinaba: char[Pos] to_be_written; ff0ab77d3d 2012-07-15 kinaba: foreach(p; may_update_list) ff0ab77d3d 2012-07-15 kinaba: if(is_hige_turn() && this[p]=='W') ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: for(int dy=-1; dy<=+1; ++dy) ff0ab77d3d 2012-07-15 kinaba: for(int dx=-1; dx<=+1; ++dx) { ff0ab77d3d 2012-07-15 kinaba: Pos q = new Pos(p.y+dy,p.x+dx); ff0ab77d3d 2012-07-15 kinaba: if( this[q] == ' ' ) ff0ab77d3d 2012-07-15 kinaba: to_be_written[q] = 'W'; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: else ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: int y = p.y; ff0ab77d3d 2012-07-15 kinaba: int x = p.x; ff0ab77d3d 2012-07-15 kinaba: char below = this[y-1,x]; ff0ab77d3d 2012-07-15 kinaba: // * ff0ab77d3d 2012-07-15 kinaba: // _ ff0ab77d3d 2012-07-15 kinaba: if(below==' ') { ff0ab77d3d 2012-07-15 kinaba: Pos q = new Pos(y-1,x); ff0ab77d3d 2012-07-15 kinaba: to_be_written[p] = ' '; ff0ab77d3d 2012-07-15 kinaba: to_be_written[q] = '*'; ff0ab77d3d 2012-07-15 kinaba: may_update_[q] = true; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: // *_ *_ ff0ab77d3d 2012-07-15 kinaba: // *_ or \_ ff0ab77d3d 2012-07-15 kinaba: else if((below=='*'||below=='\\')&&this[y-1,x+1]==' '&&this[y,x+1]==' ') { ff0ab77d3d 2012-07-15 kinaba: Pos q = new Pos(y-1,x+1); ff0ab77d3d 2012-07-15 kinaba: to_be_written[p] = ' '; ff0ab77d3d 2012-07-15 kinaba: to_be_written[q] = '*'; ff0ab77d3d 2012-07-15 kinaba: may_update_[q] = true; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: // _* ff0ab77d3d 2012-07-15 kinaba: // _* ff0ab77d3d 2012-07-15 kinaba: else if(below=='*'&&this[y-1,x-1]==' '&&this[y,x-1]==' ') { ff0ab77d3d 2012-07-15 kinaba: Pos q = new Pos(y-1,x-1); ff0ab77d3d 2012-07-15 kinaba: to_be_written[p] = ' '; ff0ab77d3d 2012-07-15 kinaba: to_be_written[q] = '*'; ff0ab77d3d 2012-07-15 kinaba: may_update_[q] = true; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: foreach(p,c; to_be_written) { ff0ab77d3d 2012-07-15 kinaba: dynamic_objects_[p] = c; ff0ab77d3d 2012-07-15 kinaba: if(c=='*' && p.y==robot_pos_.y+1 && p.x==robot_pos_.x) ff0ab77d3d 2012-07-15 kinaba: dead_ = true; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: if(lambda_pos_.empty) ff0ab77d3d 2012-07-15 kinaba: raw_data_[lift_pos_.y][lift_pos_.x] = 'O'; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void water_update() ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: if( robot_pos_.y <= water_level() ) ff0ab77d3d 2012-07-15 kinaba: air_left_ --; ff0ab77d3d 2012-07-15 kinaba: else ff0ab77d3d 2012-07-15 kinaba: air_left_ = max_air_; ff0ab77d3d 2012-07-15 kinaba: if( air_left_ < 0 ) ff0ab77d3d 2012-07-15 kinaba: dead_ = true; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: private: ff0ab77d3d 2012-07-15 kinaba: char map_get(int y, int x) const ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: if( y<1 || H<y || x<1 || W<x ) return '#'; ff0ab77d3d 2012-07-15 kinaba: Pos p = new Pos(y,x); ff0ab77d3d 2012-07-15 kinaba: if(p == robot_pos_) ff0ab77d3d 2012-07-15 kinaba: return 'R'; ff0ab77d3d 2012-07-15 kinaba: if(auto it = (p in dynamic_objects_)) ff0ab77d3d 2012-07-15 kinaba: return *it; ff0ab77d3d 2012-07-15 kinaba: if( x<0 || raw_data_[y].length<=x ) return ' '; ff0ab77d3d 2012-07-15 kinaba: return raw_data_[y][x]; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void map_set_empty(in Pos p) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: return map_set_empty(p.y, p.x); ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: void map_set_empty(int y, int x) ff0ab77d3d 2012-07-15 kinaba: { ff0ab77d3d 2012-07-15 kinaba: if( y<1 || H<y || x<1 || W<x ) return; ff0ab77d3d 2012-07-15 kinaba: if( x<0 || raw_data_[y].length<=x ) return; ff0ab77d3d 2012-07-15 kinaba: raw_data_[y][x] = ' '; ff0ab77d3d 2012-07-15 kinaba: } ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: private: ff0ab77d3d 2012-07-15 kinaba: int H_; ff0ab77d3d 2012-07-15 kinaba: int W_; ff0ab77d3d 2012-07-15 kinaba: char[][] raw_data_; ff0ab77d3d 2012-07-15 kinaba: Pos[char] trampoline_pos_; ff0ab77d3d 2012-07-15 kinaba: Pos[] razor_pos_; ff0ab77d3d 2012-07-15 kinaba: Pos[] lambda_pos_; ff0ab77d3d 2012-07-15 kinaba: Pos lift_pos_; ff0ab77d3d 2012-07-15 kinaba: Pos robot_pos_; ff0ab77d3d 2012-07-15 kinaba: char[Pos] dynamic_objects_; ff0ab77d3d 2012-07-15 kinaba: char[char] trampoline_; ff0ab77d3d 2012-07-15 kinaba: char[][char] trampoline_rev_; ff0ab77d3d 2012-07-15 kinaba: int water_base_ = 0; ff0ab77d3d 2012-07-15 kinaba: int water_pace_ = 0; ff0ab77d3d 2012-07-15 kinaba: int max_air_ = 10; ff0ab77d3d 2012-07-15 kinaba: int hige_pace_ = 25; ff0ab77d3d 2012-07-15 kinaba: int num_razor_ = 0; ff0ab77d3d 2012-07-15 kinaba: int num_lambda_ = 0; ff0ab77d3d 2012-07-15 kinaba: ff0ab77d3d 2012-07-15 kinaba: int turn_ = 0; ff0ab77d3d 2012-07-15 kinaba: int air_left_ = 0; ff0ab77d3d 2012-07-15 kinaba: bool cleared_ = false; ff0ab77d3d 2012-07-15 kinaba: bool dead_ = false; ff0ab77d3d 2012-07-15 kinaba: bool[Pos] may_update_; 6293256fec 2012-07-14 kinaba: }