@@ -8,8 +8,9 @@ public immutable int y, x; mixin DeriveCreate; mixin DeriveCompare; mixin DeriveShow; + Pos clone() { return this; } @property: Pos wait() { return this; } Pos up() { return new Pos(y+1, x); } @@ -44,8 +45,9 @@ public immutable int base, pace; mixin DeriveCreate; mixin DeriveCompare; mixin DeriveShow; + Water clone() { return this; } static load(string[string] params) { return new Water( @@ -101,8 +103,16 @@ char[][] data; Pos robot; Pos lift; int waterproof; + } + Map clone() { return new Map(this); } + this(Map m) { + foreach(s; m.data) + this.data ~= s.dup; + this.robot = m.robot.clone(); + this.lift = m.lift.clone(); + this.waterproof = m.waterproof; } this(string[] raw_data, string[string] params) { @@ -285,15 +295,31 @@ this.map = Map.load(raw_data, params); this.water = Water.load(params); this.output = new NilOutput; } + + Game clone() { return new Game(this); } + this(Game g) { + map = g.map.clone(); + water = g.water.clone(); + output = new NilOutput; + turn = g.turn; + dead = g.dead; + lambda = g.lambda; + exit_bonus = g.exit_bonus; + under_water = g.under_water; + } void set_output(Output o) { this.output = (o is null ? new NilOutput : o); } void command(char c) { if(dead || cleared) return; + scope(exit) { + if(dead || cleared) + output.flush(); + } this.output.command(c); if(c == 'A') { @@ -312,31 +338,33 @@ dead = true; } } if( map.robot.y <= water_level ) - ++under_warter; + ++under_water; else - under_warter = 0; - if( under_warter > map.waterproof ) + under_water = 0; + if( under_water > map.waterproof ) dead = true; turn += 1; } Map map; Water water; Output output; - int turn = 0; bool dead = false; int lambda = 0; int exit_bonus = 0; - int under_warter = 0; + int under_water = 0; + // TODO: when adding members, take care of clone(). + // TODO: fix this poor design. + @property { long score() { return lambda*25L*(1+exit_bonus) - turn; } int water_level() { return water.level(turn); } int water_until_rise() { return water.until_rise(turn); } bool cleared() { return exit_bonus>0; } - int hp() { return map.waterproof - under_warter; } + int hp() { return map.waterproof - under_water; } long score_if_abort_now() { return lambda*25*(1+max(1,exit_bonus)) - turn; } } }