Overview
SHA1 Hash: | 9d4aca73facc4e591f8be31b2522a4c6b5985819 |
---|---|
Date: | 2012-07-14 21:29:17 |
User: | kinaba |
Comment: | GUI+Solver revived. |
Timelines: | family | ancestors | descendants | both | trunk |
Diffs: | redesign |
Downloads: | Tarball | ZIP archive |
Other Links: | files | file ages | manifest |
Tags And Properties
- branch=trunk inherited from [16f0b5784f]
- sym-trunk inherited from [16f0b5784f]
Changes
Added src/cui_auto_main.d version [25b34c42eebd93c9]
1 +import util; 2 +import game; 3 +import output; 4 +import driver; 5 +import solver; 6 + 7 +void main(string[] args) 8 +{ 9 + Driver d = new Driver(stdin); 10 + d.addObserver!(GuardedOutput)(); 11 + Solver s = d.addObserver!(Solver)(); 12 + s.run(&d.command); 13 +}
Modified src/game.d from [cde4121762ca0c01] to [545a22e98c8c86c7].
165 165 } 166 166 167 167 void opIndexAssign(char c, Pos p) 168 168 { 169 169 this[p.y, p.x] = c; 170 170 } 171 171 172 - Pos[] lambdas() { 172 + Pos[] lambdas() const { 173 173 Pos[] ans; 174 174 for(int y=1; y<=H; ++y) 175 175 for(int x=1; x<=W; ++x) 176 176 if(this[y,x] == '\\') 177 177 ans ~= new Pos(y,x); 178 178 return ans; 179 179 } 180 180 181 - bool cleared() 181 + bool cleared() const 182 182 { 183 183 for(int y=1; y<=H; ++y) 184 184 for(int x=1; x<=W; ++x) 185 185 if(this[y,x] == 'L' || this[y,x] == 'O') 186 186 return false; 187 187 return true; 188 188 }
Modified src/gui.d from [e76b6b97ba56256b] to [508aa0ef899fe75c].
1 1 import dfl.all; 2 2 import util; 3 3 import game; 4 -import output; 5 4 import driver; 6 -//import solver; 7 -pragma(lib, "dfl.lib"); 8 5 9 -class GUI : Form, GameObserver 6 +class GUI(Solver) : Form, GameObserver 10 7 { 11 - bool on_game_changed(char c, const(Game) g, bool finished) { 12 - draw(gr, g); 13 - invalidate(); 14 - return false; 8 + this(const(Game) g) 9 + { 10 + this.solver = new Solver(g); 11 + setup_size(g.map.W, g.map.H); 12 + setup_resources(); 13 + setup_keyhandling(); 14 + draw(g); 15 + } 16 + 17 + private void delegate(char c) fn; 18 + void set_fn(F)(F f) { this.fn = f; } 19 + 20 + void run() 21 + { 22 + Application.run(this); 15 23 } 16 24 17 - private { 18 - int cell; 19 - int turn = 0; 20 - 21 - Font font; 22 - Color[char] colors; 23 - string[char] render; 24 - void delegate(char c) fn; 25 + override void on_game_changed(char c, const(Game) g, bool finished) 26 + { 27 + draw(g); 25 28 } 26 29 27 - this(const(Game) g) 28 - { 29 - noMessageFilter(); 30 - this.setStyle(ControlStyles.OPAQUE, true); 31 - this.fn = fn; 30 +private: 31 + int cell; 32 32 33 - this.paint ~= &my_paint; 34 - this.keyDown ~= &my_keydown; 35 - 33 + void setup_size(int W, int H) 34 + { 36 35 this.formBorderStyle = FormBorderStyle.FIXED_DIALOG; 37 36 this.maximizeBox = false; 38 37 this.minimizeBox = false; 39 - this.cell = min(1024/g.map.W, 640/g.map.H); 40 - this.clientSize = Size(g.map.W*cell, g.map.H*cell); 38 + this.cell = min(1024/W, 640/H); 39 + this.clientSize = Size(W*cell, H*cell); 40 + } 41 41 42 - const scrH = this.clientSize.height; 43 - const scrW = this.clientSize.width; 44 - this.gr = new MemoryGraphics(scrW, scrH); 42 + Font font; 43 + Color[char] colors; 44 + string[char] render; 45 + Graphics graphicContext; 45 46 46 - // Resources 47 + void setup_resources() 48 + { 49 + this.graphicContext = new MemoryGraphics(this.clientSize.width, this.clientSize.height); 50 + this.setStyle(ControlStyles.OPAQUE, true); 47 51 this.font = new Font("MS Gothic", cell-2, GraphicsUnit.PIXEL); 48 52 this.backColor = Color(255,255,255); 49 53 this.colors['#'] = 50 54 this.colors['.'] = Color(255,191,127); 51 55 this.colors['*'] = Color(255,127,127); 52 56 this.colors['R'] = Color(128,128,0); 53 - this.colors['D'] = Color(255,0,0); // Dead 57 + this.colors['D'] = Color(255,0,0); 54 58 this.colors['\\'] = 55 59 this.colors['L'] = 56 60 this.colors['O'] = Color(127,255,127); 57 - this.colors['W'] = Color(204,229,255); // water 58 - 61 + this.colors['W'] = Color(204,229,255); 59 62 this.render['#'] = "■"; 60 63 this.render['*'] = "✹"; 61 64 this.render['.'] = "♒"; 62 65 this.render['\\'] = "λ"; 63 66 this.render['R'] = "☃"; 64 67 this.render['D'] = "☠"; 65 68 this.render['L'] = "☒"; 66 69 this.render['O'] = "☐"; 67 - draw(gr, g); 68 - } 69 - 70 - void set_fn(F)(F f) { this.fn = f; } 71 - 72 - void run() { 73 - Application.run(this); 70 + this.paint ~= (Control c, PaintEventArgs ev) { 71 + graphicContext.copyTo(ev.graphics, Rect(0,0,this.clientSize.width,this.clientSize.height)); 72 + }; 74 73 } 75 74 76 -private: 77 - Graphics gr; 78 - 79 - void my_paint(Control, PaintEventArgs ev) 80 - { 81 - gr.copyTo(ev.graphics, Rect(0,0,this.clientSize.width,this.clientSize.height)); 82 - } 83 - 84 - void draw(Graphics gr, const(Game) g) 75 + void draw(const(Game) g) 85 76 { 86 77 int scrW = this.clientSize.width; 87 78 int scrH = this.clientSize.height; 79 + 88 80 // Fill bg. 89 - gr.fillRectangle(this.backColor, Rect(0,0,scrW,scrH)); 81 + graphicContext.fillRectangle(this.backColor, Rect(0,0,scrW,scrH)); 90 82 91 83 // Fill water. 92 84 int w = g.water_level(); 93 - gr.fillRectangle(this.colors['W'], Rect(0, scrH-cell*w-1, scrW, cell*w+1)); 85 + graphicContext.fillRectangle(this.colors['W'], Rect(0, scrH-cell*w-1, scrW, cell*w+1)); 94 86 95 87 // Paint map. 96 88 for(int y=1; y<=g.map.H; ++y) 97 89 for(int x=1; x<=g.map.W; ++x) { 98 90 Rect r = Rect(cell*(x-1), scrH-cell*y, cell, cell); 99 91 char c = g.map[y,x]; 100 92 if( c != ' ' ) { 101 93 if( c == 'R' && g.dead ) 102 94 c = 'D'; 103 - gr.drawText(this.render[c], font, this.colors[c], r); 95 + graphicContext.drawText(this.render[c], font, this.colors[c], r); 104 96 } 105 97 } 106 98 107 - set_text(g); 99 + // Update textual info. 100 + this.text = .text("Score: ", g.score, " Air: ", g.hp, " Tide: ", g.water_until_rise); 101 + invalidate(); 102 + } 103 + 104 +private: 105 + void setup_keyhandling() 106 + { 107 + noMessageFilter(); 108 + this.keyDown ~= &my_keydown; 108 109 } 109 110 110 111 void my_keydown(Control c, KeyEventArgs ev) 111 112 { 112 113 switch(ev.keyCode) 113 114 { 114 115 case Keys.DOWN: fn('D'); break; 115 116 case Keys.UP: fn('U'); break; 116 117 case Keys.LEFT: fn('L'); break; 117 118 case Keys.RIGHT: fn('R'); break; 118 119 case Keys.W: fn('W'); break; 119 120 case Keys.A: fn('A'); break; 121 + case Keys.G: fn(solver.single_step()); break; 120 122 default: break; 121 123 } 122 124 } 123 125 124 - void set_text(const(Game) g) { 125 - this.text = .text("Score: ", g.score, " Air: ", g.hp, " Tide: ", g.water_until_rise); 126 - } 127 -} 128 - 129 -void main(string[] args) 130 -{ 131 - auto d = new Driver(File(args[1])); 132 - d.addObserver!(GuardedOutput)(); 133 - GUI g = d.addObserver!(GUI)(); 134 - g.set_fn(&d.command); 135 - g.run(); 126 + Solver solver; 136 127 }
Added src/gui_main.d version [49f16753320613b8]
1 +import gui; 2 +import output; 3 +import driver; 4 +import solver; 5 +import std.stdio; 6 +pragma(lib, "dfl.lib"); 7 + 8 +void main(string[] args) 9 +{ 10 + Driver d = new Driver(stdin); 11 + d.addObserver!(GuardedOutput)(); 12 + auto g = d.addObserver!(GUI!Solver_1)(); 13 + g.set_fn(&d.command); 14 + g.run(); 15 +}
Modified src/output.d from [2ca374354297c908] to [7fa423ba9f8ebe92].
1 1 import util; 2 2 import game; 3 3 import driver; 4 -import std.c.stdlib; 5 4 import core.stdc.signal; 6 5 7 6 class NilOutput : GameObserver 8 7 { 9 8 this(const(Game) g) {} 10 - override bool on_game_changed(char c, const(Game) g, bool finished) {return false;} 9 + override void on_game_changed(char c, const(Game) g, bool finished) {} 11 10 } 12 11 13 12 class StdOutput : GameObserver 14 13 { 15 14 this(const(Game) g) {} 16 - override bool on_game_changed(char c, const(Game) g, bool finished) 15 + override void on_game_changed(char c, const(Game) g, bool finished) 17 16 { 18 17 stdout.write(c); 19 18 stdout.flush(); 20 - return false; 21 19 } 22 20 } 23 21 24 22 class GuardedOutput : GameObserver 25 23 { 26 24 this(const(Game) g) 27 25 { 28 26 setup_sigint_handling(); 29 27 ideal_log ~= g.score_if_abort_now; 30 28 } 31 29 32 - override bool on_game_changed(char c, const(Game) g, bool finished) 30 + override void on_game_changed(char c, const(Game) g, bool finished) 33 31 { 34 32 log ~= c; 35 33 score_log ~= g.score; 36 34 ideal_log ~= g.score_if_abort_now; 37 35 if(finished) 38 36 flush(); 39 - return false; 40 37 } 41 38 42 39 private: 43 40 string log; 44 41 long[] score_log; 45 42 long[] ideal_log; 46 43
Modified src/solver.d from [42db89cb5c63a7bd] to [0bb4050087a6fb3f].
1 1 import util; 2 2 import game; 3 -import output; 3 +import driver; 4 4 5 -int g_wc = 0; 6 - 7 -void act(Game g) 5 +/* 6 +interface Solver 8 7 { 9 - Pos ro = g.map.robot; 10 - Pos[] la = g.map.lambdas(); 11 - Pos li = g.map.lift; 8 + this(const(Game) g); 9 + char single_step(); 10 +} 11 +*/ 12 12 13 - char c = 'W'; 14 - if( la.empty ) { 15 - auto r = search(g, ro, li); 16 - c = r[0]; 17 - } else { 18 - Tuple!(char,int)[] cand; 19 - foreach(lam; la) 20 - cand ~= search(g, ro, lam); 21 - sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ 22 - if(c1[1] != c2[1]) 23 - return c1[1] < c2[1]; 24 - return c1[0] < c2[0]; 25 - })(cand); 26 - c = cand[0][0]; 27 - } 28 - if(c=='W') { 29 - g_wc++; 30 - if(g_wc > 10) 31 - c = 'A'; 32 - } 33 - else 34 - g_wc = 0; 35 - g.command(c); 13 +class Solver_0 14 +{ 15 + this(const(Game) g) {} 16 + char single_step() { return 'W'; } 36 17 } 37 18 38 -Tuple!(char,int) search(Game g, Pos s, Pos o) 19 +class Solver_1 39 20 { 40 - Pos[] q = [o]; 41 - bool[][] v = new bool[][](g.map.H+2, g.map.W+2); 42 - for(int step=1; q.length; ++step) { 43 - Pos[] q2; 44 - foreach(p; q) { 45 - int[] dy=[-1,+1,0,0]; 46 - int[] dx=[0,0,-1,+1]; 47 - for(int i=0; i<4; ++i) { 48 - int y = p.y+dy[i]; 49 - int x = p.x+dx[i]; 50 - if(v[y][x]) continue; 51 - if(y==s.y && x==s.x) { 52 - if(i==0) return tuple('U',step); 53 - if(i==1) return tuple('D',step); 54 - if(i==2) return tuple('R',step); 55 - if(i==3) return tuple('L',step); 56 - } else if(g.map[y,x]==' '||g.map[y,x]=='\\') { 57 - q2 ~= new Pos(y,x); 58 - v[y][x]=true; 59 - } else if(g.map[y,x]=='.' && g.map[y-1,x]!='*') { 60 - q2 ~= new Pos(y,x); 61 - v[y][x]=true; 62 - } 63 - } 21 + int g_wc = 0; 22 + 23 + Game g; 24 + this(const(Game) g) 25 + { 26 + this.g = g.clone(); 27 + } 28 + 29 + char single_step() 30 + { 31 + char c = act(g); 32 + g.command(c); 33 + return c; 34 + } 35 + 36 + char act(const(Game) g) 37 + { 38 + const Pos ro = g.map.robot; 39 + const Pos[] la = g.map.lambdas(); 40 + const Pos li = g.map.lift; 41 + 42 + char c = 'W'; 43 + if( la.empty ) { 44 + auto r = search(g, ro, li); 45 + c = r[0]; 46 + } else { 47 + Tuple!(char,int)[] cand; 48 + foreach(lam; la) 49 + cand ~= search(g, ro, lam); 50 + sort!((Tuple!(char,int) c1, Tuple!(char,int) c2){ 51 + if(c1[1] != c2[1]) 52 + return c1[1] < c2[1]; 53 + return c1[0] < c2[0]; 54 + })(cand); 55 + c = cand[0][0]; 56 + } 57 + if(c=='W') { 58 + g_wc++; 59 + if(g_wc > 10) 60 + c = 'A'; 64 61 } 65 - q = q2; 62 + else 63 + g_wc = 0; 64 + return c; 66 65 } 67 - q = [o]; 68 - v = new bool[][](g.map.H+2, g.map.W+2); 69 - for(int step=1000; q.length; ++step) { 70 - Pos[] q2; 71 - foreach(p; q) { 72 - int[] dy=[-1,+1,0,0]; 73 - int[] dx=[0,0,-1,+1]; 74 - for(int i=0; i<4; ++i) { 75 - int y = p.y+dy[i]; 76 - int x = p.x+dx[i]; 77 - if(v[y][x]) continue; 78 - if(y==s.y && x==s.x) { 79 - if(i==0) return tuple('U',step); 80 - if(i==1) return tuple('D',step); 81 - if(i==2) return tuple('R',step); 82 - if(i==3) return tuple('L',step); 83 - } else if(g.map[y,x]==' '||g.map[y,x]=='\\') { 84 - q2 ~= new Pos(y,x); 85 - v[y][x]=true; 86 - } else if(g.map[y,x]=='.'/* && g[y-1,x]!='*'*/) { 87 - q2 ~= new Pos(y,x); 88 - v[y][x]=true; 66 + 67 + Tuple!(char,int) search(in Game g, in Pos s, in Pos o) 68 + { 69 + const(Pos)[] q = [o]; 70 + bool[][] v = new bool[][](g.map.H+2, g.map.W+2); 71 + for(int step=1; q.length; ++step) { 72 + Pos[] q2; 73 + foreach(p; q) { 74 + int[] dy=[-1,+1,0,0]; 75 + int[] dx=[0,0,-1,+1]; 76 + for(int i=0; i<4; ++i) { 77 + int y = p.y+dy[i]; 78 + int x = p.x+dx[i]; 79 + if(v[y][x]) continue; 80 + if(y==s.y && x==s.x) { 81 + if(i==0) return tuple('U',step); 82 + if(i==1) return tuple('D',step); 83 + if(i==2) return tuple('R',step); 84 + if(i==3) return tuple('L',step); 85 + } else if(g.map[y,x]==' '||g.map[y,x]=='\\') { 86 + q2 ~= new Pos(y,x); 87 + v[y][x]=true; 88 + } else if(g.map[y,x]=='.' && g.map[y-1,x]!='*') { 89 + q2 ~= new Pos(y,x); 90 + v[y][x]=true; 91 + } 92 + } 93 + } 94 + q = q2; 95 + } 96 + q = [o]; 97 + v = new bool[][](g.map.H+2, g.map.W+2); 98 + for(int step=1000; q.length; ++step) { 99 + Pos[] q2; 100 + foreach(p; q) { 101 + int[] dy=[-1,+1,0,0]; 102 + int[] dx=[0,0,-1,+1]; 103 + for(int i=0; i<4; ++i) { 104 + int y = p.y+dy[i]; 105 + int x = p.x+dx[i]; 106 + if(v[y][x]) continue; 107 + if(y==s.y && x==s.x) { 108 + if(i==0) return tuple('U',step); 109 + if(i==1) return tuple('D',step); 110 + if(i==2) return tuple('R',step); 111 + if(i==3) return tuple('L',step); 112 + } else if(g.map[y,x]==' '||g.map[y,x]=='\\') { 113 + q2 ~= new Pos(y,x); 114 + v[y][x]=true; 115 + } else if(g.map[y,x]=='.'/* && g[y-1,x]!='*'*/) { 116 + q2 ~= new Pos(y,x); 117 + v[y][x]=true; 118 + } 89 119 } 90 120 } 121 + q = q2; 91 122 } 92 - q = q2; 123 + return tuple('W', int.max); 93 124 } 94 - return tuple('W', int.max); 95 -} 96 - 97 -void main(string[] args) 98 -{ 99 - auto g = Game.load(stdin); 100 - g.set_output(new GuardedOutput(g)); 101 - 102 - while(!g.dead && !g.cleared) 103 - act(g); 104 125 }