Differences From Artifact [7a4ec50fc295cb1f]:
- File
src/game.d
- 2012-07-15 15:13:15 - part of checkin [5491fa544d] on branch trunk - several fixes. (user: kinaba) [annotate]
To Artifact [b141e39ade797d94]:
- File
src/game.d
- 2012-07-15 15:38:46 - part of checkin [d40deaae5a] on branch trunk - Trampoline factored out. (user: kinaba) [annotate]
39 39
40 //////////////////////////////////////////////////////////////////////////////// 40 ////////////////////////////////////////////////////////////////////////////////
41 41
42 class Water 42 class Water
43 { 43 {
44 public immutable int base, pace; 44 public immutable int base, pace;
45 mixin DeriveCreate; 45 mixin DeriveCreate;
46 mixin DeriveCompare; <
47 mixin DeriveShow; 46 mixin DeriveShow;
48 Water clone() const { return cast(Water) this; } 47 Water clone() const { return cast(Water) this; }
49 48
50 static load(string[string] params) 49 static load(string[string] params)
51 { 50 {
52 return new Water(params.get("Water", "0").to!int(), 51 return new Water(params.get("Water", "0").to!int(),
53 params.get("Flooding", "0").to!int()); 52 params.get("Flooding", "0").to!int());
................................................................................................................................................................................
86 85
87 //////////////////////////////////////////////////////////////////////////////// 86 ////////////////////////////////////////////////////////////////////////////////
88 87
89 class Hige 88 class Hige
90 { 89 {
91 public immutable int pace; 90 public immutable int pace;
92 mixin DeriveCreate; 91 mixin DeriveCreate;
93 mixin DeriveCompare; <
94 mixin DeriveShow; 92 mixin DeriveShow;
95 Hige clone() const { return cast(Hige)this; } 93 Hige clone() const { return cast(Hige)this; }
96 94
97 static load(string[string] params) 95 static load(string[string] params)
98 { 96 {
99 return new Hige(params.get("Growth", "25").to!int()); 97 return new Hige(params.get("Growth", "25").to!int());
100 } 98 }
................................................................................................................................................................................
108 { 106 {
109 return pace ? pace-turn%pace : int.max; 107 return pace ? pace-turn%pace : int.max;
110 } 108 }
111 } 109 }
112 110
113 //////////////////////////////////////////////////////////////////////////////// 111 ////////////////////////////////////////////////////////////////////////////////
114 112
> 113 class Trampoline
> 114 {
> 115 private immutable char[] target_of_;
> 116 private immutable char[][] source_of_;
> 117 private immutable Pos[] position_of_;
> 118 private immutable char[] source_list_;
> 119 private immutable char[] target_list_;
> 120 mixin DeriveShow;
> 121 Trampoline clone() const { return cast(Trampoline) this; }
> 122 this(Map m, char[char] tramparam)
> 123 {
> 124 auto ta = new char['I'+1];
> 125 auto sr = new char[]['9'+1];
> 126 auto po = new Pos[max('I','9')+1];
> 127 char[] sl, tl;
> 128 foreach(fr,to; tramparam) {
> 129 ta[fr] = to;
> 130 sr[to] ~= fr;
> 131 }
> 132 for(int y=1; y<=m.H; ++y)
> 133 for(int x=1; x<=m.W; ++x) {
> 134 char c = m[y,x];
> 135 if('A'<=c && c<='I') {
> 136 sl ~= c;
> 137 po[c] = new Pos(y,x);
> 138 }
> 139 if('1'<=c && c<='9') {
> 140 tl ~= c;
> 141 po[c] = new Pos(y,x);
> 142 }
> 143 }
> 144 target_of_ = cast(immutable) ta;
> 145 source_of_ = cast(immutable) sr;
> 146 position_of_ = cast(immutable) po;
> 147 source_list_ = cast(immutable) sl;
> 148 target_list_ = cast(immutable) tl;
> 149 }
> 150
> 151 @property const:
> 152 const(char[]) source_list() { return source_list_; }
> 153 const(char[]) target_list() { return target_list_; }
> 154 const(char[]) source_of(char c) { return source_of_[c]; }
> 155 char target_of(char c) { return target_of_[c]; }
> 156 Pos[] source_pos(char c) {
> 157 Pos[] ps;
> 158 foreach(s; source_of(c))
> 159 ps ~= position_of_[s].clone();
> 160 return ps;
> 161 }
> 162 Pos target_pos(char c) { return position_of_[target_of_[c]].clone(); }
> 163 }
> 164
> 165 ////////////////////////////////////////////////////////////////////////////////
> 166
115 class Map 167 class Map
116 { 168 {
117 mixin DeriveShow; 169 mixin DeriveShow;
118 170
119 char[][] data; 171 char[][] data;
120 Pos robot; 172 Pos robot;
121 Pos lift; 173 Pos lift;
122 int waterproof; 174 int waterproof;
123 Pos[char] tr_target; <
124 Pos[][char] tr_source; <
125 int razor; 175 int razor;
126 int collected_lambda; 176 int collected_lambda;
127 int total_lambda; 177 int total_lambda;
128 bool cleared; 178 bool cleared;
129 Pos[] may_update; 179 Pos[] may_update;
130 180
131 Map clone() const { return new Map(this); } 181 Map clone() const { return new Map(this); }
132 this(in Map m) { 182 this(in Map m) {
133 foreach(s; m.data) 183 foreach(s; m.data)
134 this.data ~= s.dup; 184 this.data ~= s.dup;
135 this.robot = m.robot.clone(); 185 this.robot = m.robot.clone();
136 this.lift = m.lift.clone(); 186 this.lift = m.lift.clone();
137 this.waterproof = m.waterproof; 187 this.waterproof = m.waterproof;
138 this.tr_target = cast(Pos[char])m.tr_target; <
139 this.tr_source = cast(Pos[][char])m.tr_source; <
140 this.razor = m.razor; 188 this.razor = m.razor;
141 this.collected_lambda = m.collected_lambda; 189 this.collected_lambda = m.collected_lambda;
142 this.total_lambda = m.total_lambda; 190 this.total_lambda = m.total_lambda;
143 this.may_update = (cast(Map)m).may_update.dup; 191 this.may_update = (cast(Map)m).may_update.dup;
144 this.cleared = m.cleared; 192 this.cleared = m.cleared;
145 } 193 }
146 194
................................................................................................................................................................................
163 this.lift = new Pos(y,x); 211 this.lift = new Pos(y,x);
164 if(this[y,x] == '\\' || this[y,x] == '@') 212 if(this[y,x] == '\\' || this[y,x] == '@')
165 total_lambda++; 213 total_lambda++;
166 if(this[y,x] == '*' || this[y,x] == '@') 214 if(this[y,x] == '*' || this[y,x] == '@')
167 may_update ~= new Pos(y,x); 215 may_update ~= new Pos(y,x);
168 } 216 }
169 217
170 Pos[char] tr_pos; <
171 for(int y=1; y<=H; ++y) <
172 for(int x=1; x<=W; ++x) { <
173 char c = this[y,x]; <
174 if('1'<=c && c<='9' || 'A'<=c&&c<='I') <
175 tr_pos[c] = new Pos(y,x); <
176 } <
177 <
178 this.waterproof = params.get("Waterproof", "5").to!int(); 218 this.waterproof = params.get("Waterproof", "5").to!int();
179 foreach(fr,to; trampo) { <
180 tr_target[fr] = tr_pos[to]; <
181 if(to !in tr_source) tr_source[to] = []; <
182 tr_source[to] ~= tr_pos[fr]; <
183 } <
184 <
185 this.razor = params.get("Razors", "0").to!int(); 219 this.razor = params.get("Razors", "0").to!int();
186 } 220 }
187 221
188 const @property { 222 const @property {
189 int H() { return data.length; } 223 int H() { return data.length; }
190 int W() { return data[0].length; } 224 int W() { return data[0].length; }
191 } 225 }
................................................................................................................................................................................
228 ans ~= new Pos(y,x); 262 ans ~= new Pos(y,x);
229 return ans; 263 return ans;
230 } 264 }
231 265
232 Pos[] razors() const { return objects('!'); } 266 Pos[] razors() const { return objects('!'); }
233 Pos[] lambdas() const { return objects('\\'); } 267 Pos[] lambdas() const { return objects('\\'); }
234 268
235 bool command(char c, int turn, bool hige_day) | 269 bool command(char c, int turn, bool hige_day, in Trampoline tr)
236 { 270 {
237 assert( this[robot] == 'R' ); 271 assert( this[robot] == 'R' );
238 if(c=='R') return move( 0, +1, hige_day); | 272 if(c=='R') return move( 0, +1, hige_day, tr);
239 if(c=='L') return move( 0, -1, hige_day); | 273 if(c=='L') return move( 0, -1, hige_day, tr);
240 if(c=='U') return move(+1, 0, hige_day); | 274 if(c=='U') return move(+1, 0, hige_day, tr);
241 if(c=='D') return move(-1, 0, hige_day); | 275 if(c=='D') return move(-1, 0, hige_day, tr);
242 if(c=='W') return move( 0, 0, hige_day); | 276 if(c=='W') return move( 0, 0, hige_day, tr);
243 if(c=='S') return use_razor(hige_day); 277 if(c=='S') return use_razor(hige_day);
244 assert(false); 278 assert(false);
245 } 279 }
246 280
247 bool use_razor(bool hige_day) 281 bool use_razor(bool hige_day)
248 { 282 {
249 if(razor) { 283 if(razor) {
................................................................................................................................................................................
263 297
264 void emptified(Pos p) { 298 void emptified(Pos p) {
265 for(int dy=0; dy<=+1; ++dy) 299 for(int dy=0; dy<=+1; ++dy)
266 for(int dx=-1; dx<=+1; ++dx) 300 for(int dx=-1; dx<=+1; ++dx)
267 may_update ~= new Pos(p.y+dy, p.x+dx); 301 may_update ~= new Pos(p.y+dy, p.x+dx);
268 } 302 }
269 303
270 bool move(int dy, int dx, bool hige_day) | 304 bool move(int dy, int dx, bool hige_day, in Trampoline tr)
271 { 305 {
272 emptified(robot); 306 emptified(robot);
273 307
274 int y = robot.y; 308 int y = robot.y;
275 int x = robot.x; 309 int x = robot.x;
276 if( '\\' == this[y+dy,x+dx] ) 310 if( '\\' == this[y+dy,x+dx] )
277 collected_lambda++; 311 collected_lambda++;
................................................................................................................................................................................
287 char rock = this[y+dy,x+dx]; 321 char rock = this[y+dy,x+dx];
288 this[y,x]=' '; 322 this[y,x]=' ';
289 this[y+dy,x+dx]='R'; 323 this[y+dy,x+dx]='R';
290 this[y+dy*2,x+dx*2]=rock; 324 this[y+dy*2,x+dx*2]=rock;
291 robot = new Pos(y+dy,x+dx); 325 robot = new Pos(y+dy,x+dx);
292 } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') { 326 } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') {
293 this[y,x]=' '; 327 this[y,x]=' ';
294 Pos tp = tr_target[this[y+dy,x+dx]]; | 328 Pos tp = tr.target_pos(this[y+dy,x+dx]);
295 foreach(p; tr_source[this[tp]]) { | 329 foreach(p; tr.source_pos(this[tp])) {
296 emptified(p); 330 emptified(p);
297 this[p] = ' '; 331 this[p] = ' ';
298 } 332 }
299 this[tp] = 'R'; 333 this[tp] = 'R';
300 robot = tp; 334 robot = tp;
301 } 335 }
302 return update(hige_day); 336 return update(hige_day);
................................................................................................................................................................................
393 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="tar 427 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="tar
394 trampo[ss[1][0]] = ss[3][0]; 428 trampo[ss[1][0]] = ss[3][0];
395 } 429 }
396 430
397 this.map = new Map(raw_data, params, trampo); 431 this.map = new Map(raw_data, params, trampo);
398 this.water = Water.load(params); 432 this.water = Water.load(params);
399 this.hige = Hige.load(params); 433 this.hige = Hige.load(params);
> 434 this.tr = new Trampoline(this.map, trampo);
400 } 435 }
401 436
402 Game clone() const { return new Game(this); } 437 Game clone() const { return new Game(this); }
403 this(in Game g) { 438 this(in Game g) {
404 map = g.map.clone(); 439 map = g.map.clone();
405 water = g.water.clone(); 440 water = g.water.clone();
406 hige = g.hige.clone(); 441 hige = g.hige.clone();
> 442 tr = g.tr.clone();
407 turn = g.turn; 443 turn = g.turn;
408 dead = g.dead; 444 dead = g.dead;
409 under_water = g.under_water; 445 under_water = g.under_water;
410 } 446 }
411 447
412 void command(char c) 448 void command(char c)
413 { 449 {
414 assert(c != 'A'); 450 assert(c != 'A');
415 if(dead || cleared) 451 if(dead || cleared)
416 return; 452 return;
417 453
418 // TODO: clarify the event order 454 // TODO: clarify the event order
419 bool dead_now = map.command(c, turn, hige.is_growing_turn(turn)) | 455 bool dead_now = map.command(c, turn, hige.is_growing_turn(turn),
420 if( dead_now ) 456 if( dead_now )
421 dead = true; 457 dead = true;
422 if(!map.cleared) { 458 if(!map.cleared) {
423 if( map.robot.y <= water_level ) 459 if( map.robot.y <= water_level )
424 ++under_water; 460 ++under_water;
425 else 461 else
426 under_water = 0; 462 under_water = 0;
................................................................................................................................................................................
429 } 465 }
430 turn += 1; 466 turn += 1;
431 } 467 }
432 468
433 Map map; 469 Map map;
434 Water water; 470 Water water;
435 Hige hige; 471 Hige hige;
> 472 Trampoline tr;
436 int turn = 0; 473 int turn = 0;
437 bool dead = false; 474 bool dead = false;
438 int under_water = 0; 475 int under_water = 0;
439 // TODO: when adding members, take care of clone(). 476 // TODO: when adding members, take care of clone().
440 // TODO: fix this poor design. 477 // TODO: fix this poor design.
441 478
442 @property const: 479 @property const: