#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<time.h>
#include"fejs.h"
#include"object.h"


int
check_door(tlevel *lvl, tmonster *m, int door, int pdx, int pdy, int *dx, int *dy)
{
	if (lvl->m[m->y + pdy][m->x + pdx].t == door) {
		*dx = pdx;
		*dy = pdy;
		return 1;
	}
	return 0;
}

int
check_adj_doors(tlevel *lvl, tmonster *m, int door, int *dx, int *dy)
{
	int nd = 0;

	nd += check_door(lvl, m, door, -1, -1, dx, dy);
	nd += check_door(lvl, m, door, -1, 0, dx, dy);
	nd += check_door(lvl, m, door, -1, 1, dx, dy);
	nd += check_door(lvl, m, door, 0, -1, dx, dy);
	nd += check_door(lvl, m, door, 0, 0, dx, dy);
	nd += check_door(lvl, m, door, 0, 1, dx, dy);
	nd += check_door(lvl, m, door, 1, -1, dx, dy);
	nd += check_door(lvl, m, door, 1, 0, dx, dy);
	nd += check_door(lvl, m, door, 1, 1, dx, dy);

	return nd;
}

int
go_stairs(tlevel *lvl, tmonster *m, int dir, int *alvl, int limit,
	  char *unsuc, char *suc, char *impos)
{
	if (lvl->m[m->y][m->x].t != C_DOWN) {
		mwrite(unsuc);
		return 0;
	}

	if ((dir == C_DOWN ? *alvl < limit : *alvl > limit)) {
		if (dir == C_DOWN) (*alvl)++; else (*alvl)--;
		mwrite(suc);
		mflush(1);
		return 1;
	}

	mwrite(impos);
	return 0;
}


void
turn_effects(tlevel *lvl, struct player *plr)
{
	switch (random() % 500) {
		case 0:
			mwrite("You hear some strange cry...");
			break;
		case 1:
			mwrite("You hear the water dripping...");
			break;
		case 2:
		{
			int k;

			mwrite("You are alarmed by the sound of doors closed suddenly!");
			for (k = 0; k < 1000; k++) {
				int zx = random() % lvl->h;
				int zy = random() % lvl->w;

				if (lvl->m[zy][zx].t == C_ODOOR) {
					lvl->m[zy][zx].t = C_CDOOR;
					return;
				}
			}
			mwrite("Or was it just a hallucination?");
			break;
		}

		case 3:
			mwrite("You hear some strange knocking...");
			break;

		case 4:
			mwrite("*plop* *plop*");
			break;
	}
}

void
one_turn(tlevel *lvl, struct player *plr)
{
	static int walk_mode = 0, dx = 0, dy = 0;
	int alvl = 0;
	int ch;

	turn_effects(&lvl[alvl], plr);


	level_paint(&lvl[alvl], 0);
	player_paint(plr);

	if (!walk_mode)
		mflush(0);

	pmove(plr->m->x + sx, plr->m->y + sy);
	refresh();


	if (walk_mode) {
		int ms = player_move(plr, dx, dy, &lvl[alvl]);

		if (!ms)
			walk_mode = 0;

		if (lvl[alvl].m[plr->m->y][plr->m->x].t != C_FLOOR)
			walk_mode = 0;

		if (lvl[alvl].m[plr->m->y][plr->m->x].o)
			walk_mode = 0;

		if (ms != 1 && (dx || dy))
			walk_mode = 0;

		if (!dx && !dy && !(random() % 50)) {
			walk_mode = 0;
			mwrite("You feel relieved.");
		}

		usleep(10000);
		return;
	}


	ch = getch();

	pclear(0, 2);

	dx = 0; dy = 0;

	switch (ch) {
		case 'q'      :
		case '\033'   :
			mwrite("Goodbye in the future, warrior!"); mflush(1);
			pdone();
			exit(0);

		case '4':
		case KEY_LEFT :
			dx = -1;
			break;

		case '6':
		case KEY_RIGHT:
			dx = 1;
			break;

		case '8':
		case KEY_UP   :
			dy = -1;
			break;

		case '2':
		case KEY_DOWN :
			dy = 1;
			break;

		case '7':
		case KEY_HOME :
			dx = -1;
			dy = -1;
			break;

		case '1':
		case KEY_END  :
			dx = -1;
			dy = 1;
			break;

		case '3':
		case KEY_NPAGE:
			dx = 1;
			dy = 1;
			break;

		case '9':
		case KEY_PPAGE:
			dx = 1;
			dy = -1;
			break;

		case '5':
		case KEY_B2   :
			if (!player_move(plr, dx, dy, &lvl[alvl]))
				walk_mode = 0;
			break;

		case '>'      :
			go_stairs(&lvl[alvl], plr->m, C_DOWN, &alvl, pre_levels - 2,
					"You drubbed loudly. Better do not tire yourself!",
					"You descended the stairs.",
					"The stairs are falling only into an inpassable rubble...");

			player_look(plr, &lvl[alvl]);
			break;

		case '<'      :
			go_stairs(&lvl[alvl], plr->m, C_HIGH, &alvl, 0,
					"You jumped very high... ...and then landed very hard. Ouch.",
					"You climbed the stairs.",
					"You felt the first rays of sun, "
					"but your conscience pulled you back in that moment..."
					"Your duty, do you remember?");

			player_look(plr, &lvl[alvl]);
			break;

		case ','      :
			if (lvl[alvl].m[plr->m->y][plr->m->x].o)
				object_get(lvl, plr->m);
			break;

		case 'd'      :
			player_imenu(plr, 0, lvl);
			break;

		case 'i'      :
			player_imenu(plr, 1, lvl);
			break;

		case 'w'      :
			if (!take_dir("Walk", &dx, &dy, 1))
				break;
			walk_mode = 1;
			break;

		case 'l'      :
			dx = plr->m->x; dy = plr->m->y;
			while (take_place("Look", &dx, &dy)) {
				mwrite(terrains[lvl->m[dy][dx].t]);
				if (lvl->m[dy][dx].m)
					mwrite(aprintf("%s %s is waiting for you here.",
							(pre_mon[lvl->m[dy][dx].m->d].an ? "An" : "A"),
							pre_mon[lvl->m[dy][dx].m->d].name));
				if (lvl->m[dy][dx].o)
					mwrite(aprintf("%s %s is lying here.",
							(pre_obj[lvl->m[dy][dx].o->i].an ? "An" : "A"),
							pre_obj[lvl->m[dy][dx].o->i].name));
				mflush(1);
				pclear(0,2);
			}
			dx = 0; dy = 0;
			break;

		case 'h'      :
			mhistory();
			break;

		case 'o'      :
		{
			int t, nd;

			nd = check_adj_doors(&lvl[alvl], plr->m, C_CDOOR, &dx, &dy);
			if (!nd) {
				mwrite("You just turn around confused.");
				break;
			}

			if (!take_dir("Open a door", &dx, &dy, !!nd))
				break;

			t = lvl[alvl].m[plr->m->y + dy][plr->m->x + dx].t;
			switch (t) {
				case C_CDOOR:
					lvl[alvl].m[plr->m->y + dy][plr->m->x + dx].t = C_ODOOR;
					mwrite("You opened the door...");
					player_look(plr, &lvl[alvl]);
					break;
				case C_ODOOR:
					mwrite("But this door is already open!");
					break;
				default:
					mwrite("I'm certain that there is no door here, my hero.");
					break;
			}
			break;
		}

		case 'c'      :
		{
			int t, nd;

			nd = check_adj_doors(&lvl[alvl], plr->m, C_ODOOR, &dx, &dy);
			if (!nd) {
				mwrite("You just turn around confused.");
				break;
			}

			if (!take_dir("Close a door", &dx, &dy, !!nd))
				break;

			t = lvl[alvl].m[plr->m->y + dy][plr->m->x + dx].t;
			switch (t) {
				case C_ODOOR:
					lvl[alvl].m[plr->m->y + dy][plr->m->x + dx].t = C_ODOOR;
					mwrite("You closed the door...");
					player_look(plr, &lvl[alvl]);
					break;
				case C_CDOOR:
					mwrite("But this door is already closed!");
					break;
				default:
					mwrite("What door?");
					break;
			}
			break;
		}

		//      case '+'      : plr->m->l++; player_look(plr, lvl); break;
		//      case '-'      : plr->m->l--; player_look(plr, lvl); break;
	
		case 'Z'      :
			mwrite("You raise your hands and produce some mysterious mumbling... "
				"You feel the power rippling your body and concentrating, "
				"the energy is streaming through your hands, then the world "
				"flashes and you feel the extasy flooding your body!");
			switch (random() % 3) {
				case 0:
					mwrite("That's all.");
					break;
				case 1:
					mwrite("You feel like a fool here.");
					break;
				case 2:
					mwrite("Nothing else happens.");
					break;
			}
			break;

		default       :
			mwrite("Excuse me, my hero?");
			break;
	}

	if ((dx || dy) && !player_move(plr, dx, dy, &lvl[alvl]))
		walk_mode = 0;
}


int
main()
{
	struct player *plr = malloc(sizeof(struct player));
	tlevel *lvl = pre_lvl /*malloc(sizeof(tlevel))*/;

	plr->m = malloc(sizeof(tmonster));

	srandom(time(NULL));

	pinit();

	mwrite("Greetings, mortal stranger! I'm Khelerevuarbinostrulienar, the dragon "
			"which will guide you through this dungeon.");

	// level_make(lvl);

	mwrite("Welcome in the realm of the Scroll of Arcane! You will be starving, "
			"dreaming about the sunshine, fearing in the dark corners, and "
			"then... become the living legend of the Kingdom of Arrallon.");

	mflush(1); pclear(4, 12);

	plr->m->l = 5; player_teleport(plr, 13, 7, lvl);

	lvl[0].m[7][14].o = malloc(sizeof(tobj)); money_make(100, lvl[0].m[7][14].o);
	lvl[0].m[6][14].o = malloc(sizeof(tobj)); money_make(1, lvl[0].m[6][14].o);
	lvl[0].m[6][15].o = malloc(sizeof(tobj)); object_clone(1, lvl[0].m[6][15].o);
	lvl[0].m[6][16].o = malloc(sizeof(tobj)); object_clone(2, lvl[0].m[6][16].o);
	lvl[0].m[6][17].o = malloc(sizeof(tobj)); object_clone(3, lvl[0].m[6][17].o);
	lvl[0].m[6][18].o = malloc(sizeof(tobj)); object_clone(4, lvl[0].m[6][18].o);
	lvl[0].m[7][18].o = malloc(sizeof(tobj)); object_clone(5, lvl[0].m[7][18].o);
	lvl[0].m[7][19].o = malloc(sizeof(tobj)); object_clone(6, lvl[0].m[7][19].o);
	lvl[0].m[7][20].o = malloc(sizeof(tobj)); object_clone(7, lvl[0].m[7][20].o);
	lvl[0].m[8][20].m = malloc(sizeof(tmonster)); monster_clone(0, 20, 8, lvl);
	lvl[0].m[9][20].m = malloc(sizeof(tmonster)); monster_clone(1, 20, 9, lvl);
	lvl[0].m[8][21].m = malloc(sizeof(tmonster)); monster_clone(2, 21, 8, lvl);
	lvl[0].m[9][21].m = malloc(sizeof(tmonster)); monster_clone(3, 21, 9, lvl);
	lvl[0].m[8][19].m = malloc(sizeof(tmonster)); monster_clone(4, 19, 8, lvl);

	mwrite("May you survive in this terrible dungeon full of pain and direness...");

	while (1) one_turn(lvl, plr);

	return 0;
}
