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 42 class Water
43 43 {
44 44 public immutable int base, pace;
45 45 mixin DeriveCreate;
46 - mixin DeriveCompare;
47 46 mixin DeriveShow;
48 47 Water clone() const { return cast(Water) this; }
49 48
50 49 static load(string[string] params)
51 50 {
52 51 return new Water(params.get("Water", "0").to!int(),
53 52 params.get("Flooding", "0").to!int());
................................................................................
86 85
87 86 ////////////////////////////////////////////////////////////////////////////////
88 87
89 88 class Hige
90 89 {
91 90 public immutable int pace;
92 91 mixin DeriveCreate;
93 - mixin DeriveCompare;
94 92 mixin DeriveShow;
95 93 Hige clone() const { return cast(Hige)this; }
96 94
97 95 static load(string[string] params)
98 96 {
99 97 return new Hige(params.get("Growth", "25").to!int());
100 98 }
................................................................................
108 106 {
109 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 167 class Map
116 168 {
117 169 mixin DeriveShow;
118 170
119 171 char[][] data;
120 172 Pos robot;
121 173 Pos lift;
122 174 int waterproof;
123 - Pos[char] tr_target;
124 - Pos[][char] tr_source;
125 175 int razor;
126 176 int collected_lambda;
127 177 int total_lambda;
128 178 bool cleared;
129 179 Pos[] may_update;
130 180
131 181 Map clone() const { return new Map(this); }
132 182 this(in Map m) {
133 183 foreach(s; m.data)
134 184 this.data ~= s.dup;
135 185 this.robot = m.robot.clone();
136 186 this.lift = m.lift.clone();
137 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 188 this.razor = m.razor;
141 189 this.collected_lambda = m.collected_lambda;
142 190 this.total_lambda = m.total_lambda;
143 191 this.may_update = (cast(Map)m).may_update.dup;
144 192 this.cleared = m.cleared;
145 193 }
146 194
................................................................................
163 211 this.lift = new Pos(y,x);
164 212 if(this[y,x] == '\\' || this[y,x] == '@')
165 213 total_lambda++;
166 214 if(this[y,x] == '*' || this[y,x] == '@')
167 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 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 219 this.razor = params.get("Razors", "0").to!int();
186 220 }
187 221
188 222 const @property {
189 223 int H() { return data.length; }
190 224 int W() { return data[0].length; }
191 225 }
................................................................................
228 262 ans ~= new Pos(y,x);
229 263 return ans;
230 264 }
231 265
232 266 Pos[] razors() const { return objects('!'); }
233 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 271 assert( this[robot] == 'R' );
238 - if(c=='R') return move( 0, +1, hige_day);
239 - if(c=='L') return move( 0, -1, hige_day);
240 - if(c=='U') return move(+1, 0, hige_day);
241 - if(c=='D') return move(-1, 0, hige_day);
242 - if(c=='W') return move( 0, 0, hige_day);
272 + if(c=='R') return move( 0, +1, hige_day, tr);
273 + if(c=='L') return move( 0, -1, hige_day, tr);
274 + if(c=='U') return move(+1, 0, hige_day, tr);
275 + if(c=='D') return move(-1, 0, hige_day, tr);
276 + if(c=='W') return move( 0, 0, hige_day, tr);
243 277 if(c=='S') return use_razor(hige_day);
244 278 assert(false);
245 279 }
246 280
247 281 bool use_razor(bool hige_day)
248 282 {
249 283 if(razor) {
................................................................................
263 297
264 298 void emptified(Pos p) {
265 299 for(int dy=0; dy<=+1; ++dy)
266 300 for(int dx=-1; dx<=+1; ++dx)
267 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 306 emptified(robot);
273 307
274 308 int y = robot.y;
275 309 int x = robot.x;
276 310 if( '\\' == this[y+dy,x+dx] )
277 311 collected_lambda++;
................................................................................
287 321 char rock = this[y+dy,x+dx];
288 322 this[y,x]=' ';
289 323 this[y+dy,x+dx]='R';
290 324 this[y+dy*2,x+dx*2]=rock;
291 325 robot = new Pos(y+dy,x+dx);
292 326 } else if('A'<=this[y+dy,x+dx] && this[y+dy,x+dx]<='I') {
293 327 this[y,x]=' ';
294 - Pos tp = tr_target[this[y+dy,x+dx]];
295 - foreach(p; tr_source[this[tp]]) {
328 + Pos tp = tr.target_pos(this[y+dy,x+dx]);
329 + foreach(p; tr.source_pos(this[tp])) {
296 330 emptified(p);
297 331 this[p] = ' ';
298 332 }
299 333 this[tp] = 'R';
300 334 robot = tp;
301 335 }
302 336 return update(hige_day);
................................................................................
393 427 if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="targets" )
394 428 trampo[ss[1][0]] = ss[3][0];
395 429 }
396 430
397 431 this.map = new Map(raw_data, params, trampo);
398 432 this.water = Water.load(params);
399 433 this.hige = Hige.load(params);
434 + this.tr = new Trampoline(this.map, trampo);
400 435 }
401 436
402 437 Game clone() const { return new Game(this); }
403 438 this(in Game g) {
404 439 map = g.map.clone();
405 440 water = g.water.clone();
406 441 hige = g.hige.clone();
442 + tr = g.tr.clone();
407 443 turn = g.turn;
408 444 dead = g.dead;
409 445 under_water = g.under_water;
410 446 }
411 447
412 448 void command(char c)
413 449 {
414 450 assert(c != 'A');
415 451 if(dead || cleared)
416 452 return;
417 453
418 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), tr);
420 456 if( dead_now )
421 457 dead = true;
422 458 if(!map.cleared) {
423 459 if( map.robot.y <= water_level )
424 460 ++under_water;
425 461 else
426 462 under_water = 0;
................................................................................
429 465 }
430 466 turn += 1;
431 467 }
432 468
433 469 Map map;
434 470 Water water;
435 471 Hige hige;
472 + Trampoline tr;
436 473 int turn = 0;
437 474 bool dead = false;
438 475 int under_water = 0;
439 476 // TODO: when adding members, take care of clone().
440 477 // TODO: fix this poor design.
441 478
442 479 @property const: