Diff
Not logged in

Differences From Artifact [7c15481493257083]:

To Artifact [cde4121762ca0c01]:


1 import util; 1 import util; 2 import output; < 3 2 4 //////////////////////////////////////////////////////////////////////////////// 3 //////////////////////////////////////////////////////////////////////////////// 5 4 6 class Pos 5 class Pos 7 { 6 { 8 public immutable int y, x; 7 public immutable int y, x; 9 mixin DeriveCreate; 8 mixin DeriveCreate; 10 mixin DeriveCompare; 9 mixin DeriveCompare; 11 mixin DeriveShow; 10 mixin DeriveShow; 12 Pos clone() { return this; } | 11 Pos clone() const { return new Pos(y, x); } 13 12 14 @property: 13 @property: 15 Pos wait() { return this; } | 14 Pos wait() { return this.clone(); } 16 Pos up() { return new Pos(y+1, x); } 15 Pos up() { return new Pos(y+1, x); } 17 Pos down() { return new Pos(y-1, x); } 16 Pos down() { return new Pos(y-1, x); } 18 Pos left() { return new Pos(y, x-1); } 17 Pos left() { return new Pos(y, x-1); } 19 Pos right() { return new Pos(y, x+1); } 18 Pos right() { return new Pos(y, x+1); } 20 alias wait W,w; 19 alias wait W,w; 21 alias up U,u; 20 alias up U,u; 22 alias down D,d; 21 alias down D,d; ................................................................................................................................................................................ 42 41 43 class Water 42 class Water 44 { 43 { 45 public immutable int base, pace; 44 public immutable int base, pace; 46 mixin DeriveCreate; 45 mixin DeriveCreate; 47 mixin DeriveCompare; 46 mixin DeriveCompare; 48 mixin DeriveShow; 47 mixin DeriveShow; 49 Water clone() { return this; } | 48 Water clone() const { return new Water(base, pace); } 50 49 51 static load(string[string] params) 50 static load(string[string] params) 52 { 51 { 53 return new Water( 52 return new Water( 54 params.get("Water", "0").to!int(), 53 params.get("Water", "0").to!int(), 55 params.get("Flooding", "0").to!int() 54 params.get("Flooding", "0").to!int() 56 ); 55 ); 57 } 56 } 58 57 59 int level(int number_of_update) | 58 int level(int number_of_update) const 60 { 59 { 61 return pace ? base+(number_of_update/pace) : base; 60 return pace ? base+(number_of_update/pace) : base; 62 } 61 } 63 62 64 int until_rise(int number_of_update) | 63 int until_rise(int number_of_update) const 65 { 64 { 66 return pace ? pace-number_of_update%pace : int.max; 65 return pace ? pace-number_of_update%pace : int.max; 67 } 66 } 68 } 67 } 69 68 70 unittest 69 unittest 71 { 70 { ................................................................................................................................................................................ 100 } 99 } 101 100 102 char[][] data; 101 char[][] data; 103 Pos robot; 102 Pos robot; 104 Pos lift; 103 Pos lift; 105 int waterproof; 104 int waterproof; 106 105 107 Map clone() { return new Map(this); } | 106 Map clone() const { return new Map(this); } 108 this(Map m) { | 107 this(const(Map) m) { 109 foreach(s; m.data) 108 foreach(s; m.data) 110 this.data ~= s.dup; 109 this.data ~= s.dup; 111 this.robot = m.robot.clone(); 110 this.robot = m.robot.clone(); 112 this.lift = m.lift.clone(); 111 this.lift = m.lift.clone(); 113 this.waterproof = m.waterproof; 112 this.waterproof = m.waterproof; 114 } 113 } 115 114 ................................................................................................................................................................................ 136 } 135 } 137 136 138 const @property { 137 const @property { 139 int H() { return data.length; } 138 int H() { return data.length; } 140 int W() { return data[0].length; } 139 int W() { return data[0].length; } 141 } 140 } 142 141 > 142 const { 143 char opIndex(int y, int x) | 143 char opIndex(int y, int x) 144 { | 144 { 145 // Adjust coordinate to the spec. bottom-left is (1,1). | 145 // Adjust coordinate to the spec. bottom-left is (1,1). 146 --y, --x; | 146 --y, --x; 147 if(y<0||H<=y||x<0||W<=x) | 147 if(y<0||H<=y||x<0||W<=x) 148 return '#'; | 148 return '#'; 149 return data[H-1-y][x]; | 149 return data[H-1-y][x]; 150 } | 150 } 151 151 152 char opIndex(Pos p) | 152 char opIndex(Pos p) 153 { | 153 { 154 return this[p.y, p.x]; | 154 return this[p.y, p.x]; > 155 } 155 } 156 } 156 157 157 void opIndexAssign(char c, int y, int x) 158 void opIndexAssign(char c, int y, int x) 158 { 159 { 159 // Adjust coordinate to the spec. bottom-left is (1,1). 160 // Adjust coordinate to the spec. bottom-left is (1,1). 160 --y, --x; 161 --y, --x; 161 if(y<0||H<=y||x<0||W<=x) 162 if(y<0||H<=y||x<0||W<=x) ................................................................................................................................................................................ 298 return new Game(raw_data, params); 299 return new Game(raw_data, params); 299 } 300 } 300 301 301 this(string[] raw_data, string[string] params) 302 this(string[] raw_data, string[string] params) 302 { 303 { 303 this.map = Map.load(raw_data, params); 304 this.map = Map.load(raw_data, params); 304 this.water = Water.load(params); 305 this.water = Water.load(params); 305 this.output = new NilOutput; < 306 } 306 } 307 307 308 Game clone() { return new Game(this); } | 308 Game clone() const { return new Game(this); } 309 this(Game g) { | 309 this(const(Game) g) { 310 map = g.map.clone(); 310 map = g.map.clone(); 311 water = g.water.clone(); 311 water = g.water.clone(); 312 output = new NilOutput; < 313 turn = g.turn; 312 turn = g.turn; 314 dead = g.dead; 313 dead = g.dead; 315 lambda = g.lambda; 314 lambda = g.lambda; 316 exit_bonus = g.exit_bonus; 315 exit_bonus = g.exit_bonus; 317 under_water = g.under_water; 316 under_water = g.under_water; 318 } 317 } 319 318 320 void set_output(Output o) { this.output = (o is null ? new NilOutput : o < 321 < 322 void command(char c) 319 void command(char c) 323 { 320 { 324 if(dead || cleared) 321 if(dead || cleared) 325 return; 322 return; 326 scope(exit) { < 327 if(dead || cleared) < 328 output.flush(); < 329 } < 330 this.output.command(c); < 331 323 332 if(c == 'A') 324 if(c == 'A') 333 { 325 { 334 exit_bonus = 1; 326 exit_bonus = 1; 335 return; 327 return; 336 } 328 } 337 329 ................................................................................................................................................................................ 353 if( under_water > map.waterproof ) 345 if( under_water > map.waterproof ) 354 dead = true; 346 dead = true; 355 turn += 1; 347 turn += 1; 356 } 348 } 357 349 358 Map map; 350 Map map; 359 Water water; 351 Water water; 360 Output output; < 361 int turn = 0; 352 int turn = 0; 362 bool dead = false; 353 bool dead = false; 363 int lambda = 0; 354 int lambda = 0; 364 int exit_bonus = 0; 355 int exit_bonus = 0; 365 int under_water = 0; 356 int under_water = 0; 366 // TODO: when adding members, take care of clone(). 357 // TODO: when adding members, take care of clone(). 367 // TODO: fix this poor design. 358 // TODO: fix this poor design. 368 359 369 @property { | 360 @property const { 370 long score() { return lambda*25L*(1+exit_bonus) - turn; } 361 long score() { return lambda*25L*(1+exit_bonus) - turn; } 371 int water_level() { return water.level(turn); } 362 int water_level() { return water.level(turn); } 372 int water_until_rise() { return water.until_rise(turn); } 363 int water_until_rise() { return water.until_rise(turn); } 373 bool cleared() { return exit_bonus>0; } 364 bool cleared() { return exit_bonus>0; } 374 int hp() { return map.waterproof - under_water; } 365 int hp() { return map.waterproof - under_water; } 375 long score_if_abort_now() { return lambda*25*(1+max(1,exit_bonus 366 long score_if_abort_now() { return lambda*25*(1+max(1,exit_bonus 376 } 367 } 377 } 368 } 378 369 379 unittest 370 unittest 380 { 371 { 381 Game.load(["###","...","#RL"], ["xxx":"yyy"]); 372 Game.load(["###","...","#RL"], ["xxx":"yyy"]); 382 } 373 }