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