Artifact Content
Not logged in

Artifact 4262c5e337ee629cea774f36bda114e1cf4906f6


import std.algorithm;
import std.array;
import std.conv;
import std.stdio;
import std.string;
import dfl.all;

class Map
{
	private char[][] data;
	bool dead = false;
	bool cleared = false;
	int water = 0;
	int flooding = 0;
	int water_proof = 10;
	int underwater = 0;
	int flooding_counter = 0;

	this(File input)
	{
		string line;
		while( (line=input.readln().chomp()).length )
			data ~= line.dup;

		int width = 0;
		foreach(s; data)
			width = max(width, s.length);

		// space padding and sentinels
		foreach(ref s; data) {
			int p = s.length;
			s.length = width;
			s[p..$] = ' ';
			s = '#' ~ s ~ '#';
		}

		// vertical sentinel
		char[] sen = new char[width+2];
		sen[] = '#';
		data = sen.dup ~ data ~ sen;

		// flooding
		water = H-1;
		while( (line=input.readln()).length ) {
			string[] ss = line.split();
			if(ss.length==2 && ss[0]=="Water")
				water = H-1 - ss[1].to!int();
			else if(ss.length==2 && ss[0]=="Flooding")
				flooding = ss[1].to!int();
			else if(ss.length==2 && ss[0]=="Waterproof")
				water_proof = ss[1].to!int();
		}
	}

	@property const
	{
		int W() { return data[0].length; }
		int H() { return data.length; }
		string toString() {
			string result;
			foreach(i,s; data) {
				if(i) result ~= '\n';
				result ~= s.idup;
			}
			return result;
		}
	}

	int command_R() { return move(0, +1); }
	int command_L() { return move(0, -1); }
	int command_U() { return move(-1, 0); }
	int command_D() { return move(+1, 0); }
	int wait() { if(dead)return 0; update(); return -1; }
	int abort() { if(dead)return 0; cleared=true; return gained*25; }

	int move(int dy, int dx) {
		foreach(y,s; data)
		foreach(x,c; s)
			if(c == 'R')
				return move(dy, dx, y, x);
		assert(false);
	}

	int gained = 0; // TODO: atode naosu
	int move(int dy, int dx, int y, int x) {
		if(dead)
			return 0;
		int score = 0;
		if(data[y+dy][x+dx]=='\\') {
			score += 25;
			++gained;
		}
		if(data[y+dy][x+dx]=='O') {
			score += gained*50;
			cleared = true;
		}

		if(data[y+dy][x+dx]==' ' || data[y+dy][x+dx]=='.'
		   || data[y+dy][x+dx]=='\\' || data[y+dy][x+dx]=='O') {
			data[y][x]=' ';
			data[y+dy][x+dx]='R';
		} else if(dy==0 && data[y+dy][x+dx]=='*' && data[y+2*dy][x+2*dx]==' ') {
			data[y][x]=' ';
			data[y+dy][x+dx]='R';
			data[y+2*dy][x+2*dx]='*';
		}
		update();
		return score-1;
	}

	void update() {
		char[][] next;
		foreach(y,s; data)
			next ~= s.dup;

		bool lambda = false;
		for(int y=1; y+1<H; ++y)
		for(int x=1; x+1<W; ++x)
			lambda |= (data[y][x] == '\\');

		for(int y=H-2; y>=1; --y)
		for(int x=1; x+1<W; ++x) {
			if(data[y][x]=='*') {
				if(data[y+1][x]==' ') {
					next[y][x]=' ';
					next[y+1][x]='*';
					if(next[y+2][x]=='R')
						dead=true;
				}
				else if(data[y+1][x]=='*' && data[y][x+1]==' ' && data[y+1][x+1]==' ') {
					next[y][x]=' ';
					next[y+1][x+1]='*';
					if(next[y+2][x+1]=='R')
						dead=true;
				}
				else if(data[y+1][x]=='*' && data[y][x-1]==' ' && data[y+1][x-1]==' ') {
					next[y][x]=' ';
					next[y+1][x-1]='*';
					if(next[y+2][x-1]=='R')
						dead=true;
				}
				else if(data[y+1][x]=='\\' && data[y][x+1]==' ' && data[y+1][x+1]==' ') {
					next[y][x]=' ';
					next[y+1][x+1]='*';
					if(next[y+2][x+1]=='R')
						dead=true;
				}
			}
			else if(data[y][x]=='L') {
				if(!lambda)
					next[y][x] = 'O';
			}
		}
		data = next;

		if(flooding) {
			flooding_counter ++;
			if(flooding_counter == flooding) {
				flooding_counter = 0;
				water --;
			}
			bool wa = false;
			for(int y=water; y+1<H; ++y)
			for(int x=1; x+1<W; ++x)
				if(data[y][x]=='R') {
					wa = true;
					underwater++;
					if(underwater > water_proof)
						dead = true;
				}
			if(!wa)
				underwater = 0;
		}
	}

	int clever()
	{
		if(dead)
			return 0;
		int sy,sx;
		int[] ly,lx;
		int oy,ox;
		for(int y=0; y<H; ++y)
		for(int x=0; x<W; ++x)
			if(data[y][x]=='R')
				sy=y, sx=x;
			else if(data[y][x]=='\\')
				ly~=y, lx~=x;
			else if(data[y][x]=='O')
				oy=y, ox=x;
		if(ly.length==0)
			return goal(sy,sx,oy,ox);
		return wait();
	}
	int goal(int sy, int sx, int oy, int ox)
	{
	}
}

class MyForm : Form
{
	Map m;
	int score;

	this(Map m)
	{
		noMessageFilter();
		this.m = m;
		this.text = .text("Score: ", score, "  air[",m.water_proof-m.underwater,"]");
		this.keyDown ~= &myKey;
		this.score = 0;
	}
	override void onResize(EventArgs ev) {
		invalidate();
	}
	override void onPaint(PaintEventArgs ev)
	{
		int Z = min(this.clientSize.width/(m.W-2), this.clientSize.height/(m.H-2));
		Font font = new Font("MS Gothic", Z-4);
		Graphics g = ev.graphics;
		g.fillRectangle(Color(0,233,255), Rect(0,Z*(m.water-1),this.clientSize.width,this.clientSize.height-(Z*(m.water-1))));
		for(int y=1; y+1<m.H; ++y)
		for(int x=1; x+1<m.W; ++x) {
			if(m.data[y][x]=='*') {
				g.drawText("岩", font, Color(0,0,0), Rect((x-1)*Z, (y-1)*Z, Z, Z));
			}
			if(m.data[y][x]=='\\') {
				g.drawText("λ", font, Color(0,255,0), Rect((x-1)*Z, (y-1)*Z, Z, Z));
			}
			if(m.data[y][x]=='R') {
				if(m.dead)
					g.drawText("Я", font, Color(255,0,0), Rect((x-1)*Z, (y-1)*Z, Z, Z));
				else
					g.drawText("R", font, Color(128,128,0), Rect((x-1)*Z, (y-1)*Z, Z, Z));
			}
			if(m.data[y][x]=='L') {
				g.drawText("扉", font, Color(255,255,0), Rect((x-1)*Z, (y-1)*Z, Z, Z));
			}
			if(m.data[y][x]=='O') {
				g.drawText("外", font, Color(255,255,0), Rect((x-1)*Z, (y-1)*Z, Z, Z));
			}
			if(m.data[y][x]=='#') {
				g.drawText("#", font, Color(0,0,0), Rect((x-1)*Z, (y-1)*Z, Z, Z));
			}
			if(m.data[y][x]=='.') {
				g.drawText("・", font, Color(128,40,0), Rect((x-1)*Z, (y-1)*Z, Z, Z));
			}
		}
	}
	void myKey(Control c, KeyEventArgs ev)
	{
		switch(ev.keyCode)
		{
		case Keys.DOWN:
			score += m.command_D();
			write("D");
			stdout.flush();
			break;
		case Keys.UP:
			score += m.command_U();
			write("U");
			stdout.flush();
			break;
		case Keys.LEFT:
			score += m.command_L();
			write("L");
			stdout.flush();
			break;
		case Keys.RIGHT:
			score += m.command_R();
			write("R");
			stdout.flush();
			break;
		case Keys.W:
			score += m.wait();
			write("W");
			stdout.flush();
			break;
		case Keys.A:
			score += m.abort();
			write("A");
			stdout.flush();
			break;
		case Keys.G:
			score += m.clever();
			write("_");
			stdout.flush();
			break;
		default:
			break;
		}
		if(m.cleared) {
			writeln();
			writeln("Score: ", score);
			Application.exit();
		}
		this.text = .text("Score: ", score, "  air[",m.water_proof-m.underwater,"]");
		invalidate();
	}
}

void main(string[] args)
{
	Form myForm = new MyForm(new Map(File(args[1])));
	Application.run(myForm);
}