Check-in [ff0ab77d3d]
Not logged in
Overview
SHA1 Hash:ff0ab77d3d8809af945fc63b6c56a3863b5f3a2e
Date: 2012-07-15 20:17:59
User: kinaba
Comment:new game class.
Timelines: family | ancestors | descendants | both | trunk
Diffs: redesign
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified score_memo.txt from [d46da9814cb8619d] to [95f0626c958d6d31].

1 1 contest1 212! 2 2 contest2 280? 3 3 contest3 275! 4 4 contest4 561? 5 5 contest5 1281? 6 -contest6 737 6 +contest6 737 // deadend trap 7 7 contest7 867? 8 -contest8 1245 8 +contest8 1245 // tricky 9 9 contest9 3042? 10 -contest10 2076 11 -flood1 569 10 +contest10 2076 // * on lambda, must move * first 11 +flood1 569 // too slow, because of 1-left danger lambda 12 12 flood2 280? 13 -flood3 802 14 -flood4 970 13 +flood3 802 // too slow, drown 14 +flood4 970 // incorrect order of digging 15 15 flood5 561? 16 -trampoline1 291 16 +trampoline1 291 // * on trampoline. must move * first 17 17 trampoline2 1728? 18 -trampoline3 698 18 +trampoline3 698 // * on trampoline target. must move * first. 19 19 beard1 856? 20 -beard2 2792 21 -beard3 811 22 -beard4 677 20 +beard2 2792 // hutsu-ni muzui 21 +beard3 811 // tricky. must hurry to cut hige. 22 +beard4 677 // deadend trap

Modified src/cui_auto_main.d from [b38d60ea39d11e6e] to [80ad58f91e39ad66].

14 14 fin = finished; 15 15 } 16 16 } 17 17 18 18 void main(string[] args) 19 19 { 20 20 Driver d = new Driver(stdin); 21 - d.addObserver!(GuardedOutput)(); 22 - auto c = d.addObserver!(CUI!MainSolver)(); 21 +// d.addObserver!(GuardedOutput)(); 22 + d.addObserver!(StdOutput)(); 23 +// auto c = d.addObserver!(CUI!MainSolver)(); 24 + auto c = d.addObserver!(CUI!Solver_0)(); 23 25 while(!c.fin) 24 26 d.command(c.solver.single_step()); 25 27 }

Modified src/game.d from [e25c75ea96d80507] to [9428bbab7d2bc9a8].

346 346 } 347 347 data = next; 348 348 return dead; 349 349 } 350 350 } 351 351 352 352 //////////////////////////////////////////////////////////////////////////////// 353 - 353 +/* 354 354 class Game 355 355 { 356 356 mixin DeriveShow; 357 357 358 358 static Game load(File input) 359 359 { 360 360 string[] raw_data; ................................................................................ 440 440 long score() { return lambda*(dead ? 25L : cleared ? 75L : 50L) - turn; } 441 441 int water_level() { return water.level(turn); } 442 442 int water_until_rise() { return water.until_rise(turn); } 443 443 int hige_until_rise() { return map.hige.until_rise(turn); } 444 444 int hp() { return map.waterproof - under_water; } 445 445 } 446 446 } 447 +*/ 448 + 449 +//////////////////////////////////////////////////////////////////////////////// 450 + 451 +class Game 452 +{ 453 +public: 454 + this(File input) 455 + { 456 + // Read map data 457 + string[] map_data_lines; 458 + for(string line; !(line=input.readln().chomp()).empty; ) 459 + map_data_lines ~= line; 460 + 461 + // H*W 462 + H_ = map_data_lines.length; 463 + W_ = 0; 464 + foreach(mdl; map_data_lines) 465 + W_ = max(W_, mdl.length); 466 + 467 + // Copy to modifiable buffer and adjust coordinates. 468 + raw_data_ = new char[][H_+1]; 469 + foreach(i,mdl; map_data_lines) { 470 + char[] buf = new char[mdl.length+1]; 471 + buf[0] = '#'; 472 + buf[1..$] = mdl[]; 473 + raw_data_[H_-i] = buf; 474 + } 475 + 476 + // Detect objects 477 + for(int y=1; y<=H_; ++y) 478 + for(int x=1; x<raw_data_[y].length; ++x) 479 + { 480 + char c = raw_data_[y][x]; 481 + switch(c) 482 + { 483 + case '#': 484 + case '.': 485 + case ' ': 486 + break; 487 + case 'L': 488 + case 'O': 489 + lift_pos_ = new Pos(y,x); 490 + break; 491 + case 'A': .. case 'I': 492 + case '1': .. case '9': 493 + trampoline_pos_[c] = new Pos(y,x); 494 + break; 495 + case '!': 496 + razor_pos_ ~= new Pos(y,x); 497 + break; 498 + case '\\': 499 + lambda_pos_ ~= new Pos(y,x); 500 + break; 501 + 502 + // Moving objects are erased from raw_data_ 503 + case 'R': 504 + robot_pos_ = new Pos(y,x); 505 + raw_data_[y][x] = ' '; 506 + break; 507 + case '*': 508 + case 'W': 509 + dynamic_objects_[new Pos(y,x)] = c; 510 + raw_data_[y][x] = ' '; 511 + if(c=='*') 512 + may_update_[new Pos(y,x)] = true; 513 + break; 514 + default: 515 + assert(false); 516 + } 517 + } 518 + 519 + // Read other parameters 520 + for(string line; !(line=input.readln()).empty; ) 521 + { 522 + string[] ss = line.split(); 523 + if( ss.length == 2 ) 524 + switch(ss[0]) 525 + { 526 + case "Water": water_base_ = ss[1].to!int(); break; 527 + case "Flooding": water_pace_ = ss[1].to!int(); break; 528 + case "Waterproof": max_air_ = ss[1].to!int(); break; 529 + case "Growth": hige_pace_ = ss[1].to!int(); break; 530 + case "Razors": num_razor_ = ss[1].to!int(); break; 531 + default: assert(false); 532 + } 533 + if( ss.length == 4 && ss[0]=="Trampoline" && ss[2]=="targets" ) 534 + { 535 + char fr=ss[1][0], to=ss[3][0]; 536 + trampoline_[fr] = to; 537 + if(to !in trampoline_rev_) trampoline_rev_[to] = []; 538 + trampoline_rev_[to] ~= fr; 539 + } 540 + } 541 + 542 + air_left_ = max_air_; 543 + } 544 + 545 + @property const { 546 + int H() { return H_; } 547 + int W() { return W_; } 548 + char trampoline(char c) { return (c in trampoline_ ? trampoline_[c] : 0); } 549 + int water_level() { 550 + return water_pace_ ? water_base_ + turn_/water_pace_ : water_base_; 551 + } 552 + int water_until_rise() { 553 + return water_pace_ ? water_pace_ - turn_%water_pace_ : int.max; 554 + } 555 + int hige_until_rise() { 556 + return hige_pace_ ? hige_pace_ - turn_%hige_pace_ : int.max; 557 + } 558 + bool is_hige_turn() { 559 + return hige_pace_ ? turn_%hige_pace_ == hige_pace_-1 : false; 560 + } 561 + int hp() { return air_left_; } 562 + int num_razor() { return num_razor_; } 563 + bool cleared() { return cleared_; } 564 + bool dead() { return dead_; } 565 + long score() { return num_lambda_*(dead_ ? 25L : cleared_ ? 75L : 50L) - turn_; } 566 + } 567 + const { 568 + char opIndex(in Pos p) { return opIndex(p.y, p.x); } 569 + char opIndex(int y, int x) { return map_get(y, x); } 570 + } 571 + 572 +public: 573 + void command(char c) 574 + { 575 + if(dead || cleared) 576 + return; 577 + 578 + if(c == 'U') command_move(+1, 0); 579 + if(c == 'D') command_move(-1, 0); 580 + if(c == 'L') command_move(0, -1); 581 + if(c == 'R') command_move(0, +1); 582 + if(c == 'S') use_razor(); 583 + if(c == 'W') {} 584 + 585 + if(cleared) 586 + return; 587 + 588 + map_update(); 589 + water_update(); 590 + turn_ ++; 591 + } 592 + 593 + void command_move(int dy, int dx) 594 + { 595 + int y = robot_pos_.y, x = robot_pos_.x; 596 + char c = this[y+dy, x+dx]; 597 + Pos p = new Pos(y+dy, x+dx); 598 + 599 + switch(c){ 600 + case 'O': 601 + cleared_ = true; 602 + move_robot_to(p); 603 + break; 604 + case '\\': 605 + take_lambda_at(p); 606 + move_robot_to(p); 607 + break; 608 + case '!': 609 + take_razor_at(p); 610 + move_robot_to(p); 611 + break; 612 + case 'A': .. case 'I': 613 + enter_trampoline_at(p, c); 614 + break; 615 + case ' ': 616 + case '.': 617 + move_robot_to(p); 618 + break; 619 + case '*': 620 + if(dy!=0 || this[y,x+dx*2]!=' ') 621 + break; 622 + move_robot_to(p); 623 + push_rock(p, new Pos(y,x+dx*2)); 624 + break; 625 + default: 626 + break; 627 + } 628 + } 629 + 630 + void use_razor() 631 + { 632 + if(num_razor_ == 0) 633 + return; 634 + num_razor_ --; 635 + 636 + for(int dy=-1; dy<=+1; ++dy) 637 + for(int dx=-1; dx<=+1; ++dx) if(dy||dx) 638 + { 639 + Pos p = new Pos(robot_pos_.y+dy, robot_pos_.x+dx); 640 + if(auto it = p in dynamic_objects_) 641 + if(*it == 'W') { 642 + something_gone(p); 643 + dynamic_objects_.remove(p); 644 + } 645 + } 646 + } 647 + 648 + void take_lambda_at(Pos p) 649 + { 650 + map_set_empty(p); 651 + num_lambda_ ++; 652 + lambda_pos_ = lambda_pos_.erase(p); 653 + } 654 + 655 + void take_razor_at(Pos p) 656 + { 657 + map_set_empty(p); 658 + num_razor_ ++; 659 + razor_pos_ = razor_pos_.erase(p); 660 + } 661 + 662 + void enter_trampoline_at(Pos p, char c) 663 + { 664 + char d = trampoline(c); 665 + foreach(cc; trampoline_rev_[d]) { 666 + Pos pp = trampoline_pos_[cc]; 667 + something_gone(pp); 668 + map_set_empty(pp); 669 + } 670 + move_robot_to(trampoline_pos_[d]); 671 + } 672 + 673 + void move_robot_to(Pos p) 674 + { 675 + something_gone(robot_pos_); 676 + map_set_empty(p.y, p.x); 677 + robot_pos_ = p; 678 + } 679 + 680 + void push_rock(Pos fr, Pos to) 681 + { 682 + dynamic_objects_.remove(fr); 683 + dynamic_objects_[to] = '*'; 684 + may_update_[to] = true; 685 + } 686 + 687 + void something_gone(Pos p) 688 + { 689 + for(int dy=0; dy<=+1; ++dy) 690 + for(int dx=-1; dx<=+1; ++dx) if(dy||dx) 691 + may_update_[new Pos(p.y+dy,p.x+dx)] = true; 692 + } 693 + 694 + void map_update() 695 + { 696 + Pos[] may_update_list; 697 + foreach(p,_; may_update_) 698 + if(this[p] == '*') 699 + may_update_list ~= p; 700 + may_update_ = null; 701 + 702 + if( is_hige_turn() ) 703 + foreach(p,c; dynamic_objects_) 704 + if(c == 'W') 705 + may_update_list ~= p; 706 + 707 + sort(may_update_list); 708 + char[Pos] to_be_written; 709 + foreach(p; may_update_list) 710 + if(is_hige_turn() && this[p]=='W') 711 + { 712 + for(int dy=-1; dy<=+1; ++dy) 713 + for(int dx=-1; dx<=+1; ++dx) { 714 + Pos q = new Pos(p.y+dy,p.x+dx); 715 + if( this[q] == ' ' ) 716 + to_be_written[q] = 'W'; 717 + } 718 + } 719 + else 720 + { 721 + int y = p.y; 722 + int x = p.x; 723 + char below = this[y-1,x]; 724 + // * 725 + // _ 726 + if(below==' ') { 727 + Pos q = new Pos(y-1,x); 728 + to_be_written[p] = ' '; 729 + to_be_written[q] = '*'; 730 + may_update_[q] = true; 731 + } 732 + // *_ *_ 733 + // *_ or \_ 734 + else if((below=='*'||below=='\\')&&this[y-1,x+1]==' '&&this[y,x+1]==' ') { 735 + Pos q = new Pos(y-1,x+1); 736 + to_be_written[p] = ' '; 737 + to_be_written[q] = '*'; 738 + may_update_[q] = true; 739 + } 740 + // _* 741 + // _* 742 + else if(below=='*'&&this[y-1,x-1]==' '&&this[y,x-1]==' ') { 743 + Pos q = new Pos(y-1,x-1); 744 + to_be_written[p] = ' '; 745 + to_be_written[q] = '*'; 746 + may_update_[q] = true; 747 + } 748 + } 749 + 750 + foreach(p,c; to_be_written) { 751 + dynamic_objects_[p] = c; 752 + if(c=='*' && p.y==robot_pos_.y+1 && p.x==robot_pos_.x) 753 + dead_ = true; 754 + } 755 + 756 + if(lambda_pos_.empty) 757 + raw_data_[lift_pos_.y][lift_pos_.x] = 'O'; 758 + } 759 + 760 + void water_update() 761 + { 762 + if( robot_pos_.y <= water_level() ) 763 + air_left_ --; 764 + else 765 + air_left_ = max_air_; 766 + if( air_left_ < 0 ) 767 + dead_ = true; 768 + } 769 + 770 +private: 771 + char map_get(int y, int x) const 772 + { 773 + if( y<1 || H<y || x<1 || W<x ) return '#'; 774 + Pos p = new Pos(y,x); 775 + if(p == robot_pos_) 776 + return 'R'; 777 + if(auto it = (p in dynamic_objects_)) 778 + return *it; 779 + if( x<0 || raw_data_[y].length<=x ) return ' '; 780 + return raw_data_[y][x]; 781 + } 782 + 783 + void map_set_empty(in Pos p) 784 + { 785 + return map_set_empty(p.y, p.x); 786 + } 787 + 788 + void map_set_empty(int y, int x) 789 + { 790 + if( y<1 || H<y || x<1 || W<x ) return; 791 + if( x<0 || raw_data_[y].length<=x ) return; 792 + raw_data_[y][x] = ' '; 793 + } 794 + 795 +private: 796 + int H_; 797 + int W_; 798 + char[][] raw_data_; 799 + Pos[char] trampoline_pos_; 800 + Pos[] razor_pos_; 801 + Pos[] lambda_pos_; 802 + Pos lift_pos_; 803 + Pos robot_pos_; 804 + char[Pos] dynamic_objects_; 805 + char[char] trampoline_; 806 + char[][char] trampoline_rev_; 807 + int water_base_ = 0; 808 + int water_pace_ = 0; 809 + int max_air_ = 10; 810 + int hige_pace_ = 25; 811 + int num_razor_ = 0; 812 + int num_lambda_ = 0; 813 + 814 + int turn_ = 0; 815 + int air_left_ = 0; 816 + bool cleared_ = false; 817 + bool dead_ = false; 818 + bool[Pos] may_update_; 819 +}

Modified src/gui.d from [d4577900b4db97c1] to [e84cacd6262f93a7].

4 4 import driver; 5 5 6 6 class GUI(Solver) : Form, GameObserver 7 7 { 8 8 this(in Game g) 9 9 { 10 10 this.solver = new Solver(g); 11 - setup_size(g.map.W, g.map.H); 11 + setup_size(g.W, g.H); 12 12 setup_resources(g); 13 13 draw(g); 14 14 } 15 15 16 16 private void delegate(char c) fn; 17 17 void set_fn(F)(F f) { this.fn = f; } 18 18 ................................................................................ 79 79 this.render['\\'] = "λ"; 80 80 this.render['R'] = "☃"; 81 81 this.render['d'] = "☠"; 82 82 this.render['L'] = "☒"; 83 83 this.render['O'] = "☐"; 84 84 this.render['W'] = "ꔣ"; 85 85 this.render['!'] = "✄"; 86 - foreach(c,tp; g.map.tr_target) { 87 - char d = g.map[tp]; 88 - this.render[c] = [cast(dchar)('☢'+d-'1')].to!string(); 89 - } 86 + foreach(char c; 'A'..'J') this.render[c] = [cast(dchar)('☢'+g.trampoline(c)-'1')].to!string(); 90 87 foreach(char c; '1'..':') this.render[c] = [cast(dchar)('☢'+c-'1')].to!string(); 91 88 this.paint ~= (Control c, PaintEventArgs ev) { 92 89 graphicContext.copyTo(ev.graphics, Rect(0,0,this.clientSize.width,this.clientSize.height)); 93 90 }; 94 91 } 95 92 96 93 void draw(in Game g) ................................................................................ 102 99 graphicContext.fillRectangle(this.backColor, Rect(0,0,scrW,scrH)); 103 100 104 101 // Fill water. 105 102 int w = g.water_level(); 106 103 graphicContext.fillRectangle(this.colors['w'], Rect(0, scrH-cell*w-1, scrW, cell*w+1)); 107 104 108 105 // Paint map. 109 - for(int y=1; y<=g.map.H; ++y) 110 - for(int x=1; x<=g.map.W; ++x) { 106 + for(int y=1; y<=g.H; ++y) 107 + for(int x=1; x<=g.W; ++x) { 111 108 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); 112 - char c = g.map[y,x]; 109 + char c = g[y,x]; 113 110 if( c != ' ' ) { 114 111 if( c == 'R' && g.dead ) 115 112 c = 'd'; 116 113 graphicContext.drawText(this.render[c], font, this.colors[c], r); 117 114 } 118 115 } 119 116 120 117 // Update textual info. 121 118 this.text = .text( 122 119 "Score: ", g.score, 123 120 " Air: ", g.hp, 124 121 " Tide: ", g.water_until_rise, 125 122 " Wadler: ", g.hige_until_rise, 126 - " Razor: ", g.map.razor); 123 + " Razor: ", g.num_razor); 127 124 invalidate(); 128 125 } 129 126 130 127 private: 131 128 void setup_keyhandling() 132 129 { 133 130 noMessageFilter();

Modified src/gui_main.d from [05082d0f328d756c] to [1d7ea5dfabc56eb4].

4 4 import solver; 5 5 import std.stdio; 6 6 pragma(lib, "dfl.lib"); 7 7 8 8 void main(string[] args) 9 9 { 10 10 Driver d = new Driver(stdin); 11 - d.addObserver!(GuardedOutput)(); 12 - auto g = d.addObserver!(GUI!MainSolver)(); 11 +// d.addObserver!(GuardedOutput)(); 12 + d.addObserver!(StdOutput)(); 13 +// auto g = d.addObserver!(GUI!MainSolver)(); 14 + auto g = d.addObserver!(GUI!Solver_0)(); 13 15 g.set_fn(&d.command); 14 16 g.run(); 15 17 }

Modified src/output.d from [045b845268918546] to [b301f73c74ef62f4].

14 14 this(in Game g) {} 15 15 override void on_game_changed(char c, in Game g, bool finished) 16 16 { 17 17 stdout.write(c); 18 18 stdout.flush(); 19 19 } 20 20 } 21 - 21 +/* 22 22 class GuardedOutput : GameObserver 23 23 { 24 24 this(in Game g) 25 25 { 26 26 setup_sigint_handling(); 27 27 score_log ~= g.score; 28 28 flushed = false; ................................................................................ 68 68 { 69 69 assert(g_output is null); 70 70 g_output = this; 71 71 extern(C) static void catch_sigint(int) { g_output.flush(); application_exit(); } 72 72 core.stdc.signal.signal(SIGINT, &catch_sigint); 73 73 } 74 74 } 75 +*/

Modified src/solver.d from [393baf841678f948] to [42b4ef037737dcd0].

3 3 4 4 class Solver_0 5 5 { 6 6 this(in Game g) {} 7 7 char single_step() { return 'W'; } 8 8 void force(char c) {} 9 9 } 10 - 10 +/* 11 11 class Solver_1 12 12 { 13 13 int wait_count = 0; 14 14 int choke_count = 0; 15 15 16 16 Game g; 17 17 this(in Game g) ................................................................................ 383 383 plan_broken = true; 384 384 } 385 385 else 386 386 plan = plan[1..$]; 387 387 } 388 388 } 389 389 390 -alias Solver_2!(Solver_1) MainSolver; 391 -//alias Solver_1 MainSolver; 390 +//alias Solver_2!(Solver_1) MainSolver; 391 +alias Solver_1 MainSolver; 392 +*/

Modified src/util.d from [41ba420d0c49ce8d] to [b76be1f6ad977d56].

3 3 public import std.conv; 4 4 public import std.range; 5 5 public import std.stdio; 6 6 public import std.string; 7 7 public import std.typecons; 8 8 public import std.math; 9 9 import std.c.stdlib; 10 + 11 +T[] erase(T,V)(T[] xs, V y) 12 +{ 13 + foreach(i,x; xs) 14 + if(x == y) 15 + return xs[0..i]~xs[i+1..$]; 16 + return xs; 17 +} 10 18 11 19 // To avoide the following ICE: 12 20 // src\phobos\std\algorithm.d(4552): 13 21 // Error: function std.algorithm.count!("a == b",string,char).count 14 22 // compiler error, parameter 'value', bugzilla 2962? 15 23 // Assertion failure: '0' on line 717 in file 'glue.c' 16 24 int count(T,V)(T[] a, V v)