#include <dos.h>
#include <alloc.h>
#include <stdio.h>
#include <conio.h>
#include <wgt.h>
#include <scroll.h>
/* WordUp Graphics Toolkit Scrolling Demo
   Feel free to use any part of this program in your own...

   Munchkin: A simple platform type game starring a munchkin as
	     the main character
*/


#define YOU 37


void checkfeet(void);
void checkhead(void);
void checkright(void);
void checkleft(void);
// These find out if you are hitting a wall in each direction

void findelevators(void);
// Search for elevators and store in an array, similar to the technique
// used in forest.c

void upelev(void);
void downelev(void);
// Move and elevator up or down.

void checkelevators(void);
// Sees if elevators needs to drop

void moveguys(void);
// Move the bad guys around, take care of them bumping into walls.


int ox,oy;  // old x and y coords, in case you hit a wall
int dir;    // the direction you are heading,
int anim;   // Running animation counter
int jumping;// Nothing under your feet?
int addy;   // Amount to add to y coord if you're falling or jumping.

int spx,spy;
int feet1,feet2,head1,head2;
int i;

wgtmap mymap;			// our world map

int kbdon[35]={0,0,0,0,0,0};	// our keyboard on/off array;
int kbdscanlist[35]={72,80,75,77,1,29};	// our keyboard scan codes;
// You must have the above two if you want the keyboard interrupt 

color palette[256];		// our palette of colours

block blocks[201];		// our blocks for the map
block sprites[201];		// our sprites 


typedef struct {
    int curheight;   // current height
    int origy,origx; // original x and y, before game started
    int timer;       // count down before it starts falling
    } elevator;

elevator elev[30]; // make room for 30 elevators


int replace[200]; // stores which tile was behind the elevator
int elevup=-1;
int numelev=0;    // total number of elevators


void main(void)
{
printf("Wordup Graphics Toolkit     4-WAY SCROLLING DEMO\n");
printf("Arrow keys move, CTRL jumps. Up/down looks in direction or operates\n");
printf("elevators.\n");
printf("\nPress any key\n\n");
getch();

vga256();					// init
wloadsprites(&palette,"munchmap.spr",blocks);    	// load blocks
wloadsprites(&palette,"munchkin.spr",sprites);    	// load sprites

mymap=wloadmap("munch.wmp");		// load our world map

findelevators();  // search and store the elevators

winitscroll(13,9);				// make a 13x9 box
						// for the scrolling

wnormscreen();					// go back to normal screen
wcls(0);					// clear it
wbutt(0,0,319,199);

wshowwindow(0,10,mymap);			// start looking at world
						// at 0,10
installkbd();					// start new keyboard interrupt

numsprites=40;
wobject[YOU].on=1; wobject[YOU].x=16; wobject[YOU].y=242; wobject[YOU].num=1;

jumping=0; addy=0;
anim=2;

do
{
spx=0; 		// scrolling x speed
spy=0;		// scrolling y speed
ox=wobject[YOU].x;  // store old x and y coords
oy=wobject[YOU].y;

if (jumping==1) // increase addy to simulate gravity
  addy+=2;
if (addy>15)    // can't fall more than 15 pixels at a time
   addy=15;

if ((kbdon[5]==1) & (jumping==0))  // Jump up
   {
   jumping=1;
   addy=-14;
   }

if (kbdon[2]==1)		// Pressing left
  {
  wobject[YOU].x-=8;
  checkleft();
  if (dir !=1)   // if you are facing right, reset the animation
    {
    dir=1;
    anim=5;
    }
  anim++;
  if (anim>8)  // cycle through running animation
    anim=5;
  }
else if (kbdon[3]==1)	// Pressing right
  {
  wobject[YOU].x+=8;
  checkright();
  if (dir !=2) // reset animation
    {
    dir=2;
    anim=1;
    }
  anim++;
  if (anim>4) // running animatio loop
    anim=1;
  }

wobject[YOU].num=anim;	// set the object to the current animation

if (wobject[YOU].x==ox)	// If you didn't move left or right,
  if (dir==1)
     wobject[YOU].num=9;    // show the non-running sprite
  else wobject[YOU].num=1;  // for each direction

wobject[YOU].y+=addy; 	// add the jumping or falling amount

if (wobject[YOU].y<0) wobject[YOU].y=0; // can't jump off top of screen
if (addy<0)	// if jumping up,
   checkhead(); // make sure you don't bump your head


if ((jumping==1))      // set to a different sprite if you are jumping
  if (dir==1) 	       // so you don't run in the air
     wobject[YOU].num=6;
  else wobject[YOU].num=2;

 checkfeet();		// check what is under your feet

spx=wobject[YOU].x-worldx-windowmaxx/2;	// find out if we need to scroll
spy=wobject[YOU].y-worldy-windowmaxy/2;

if (kbdon[0]==1)		// Pressing up
  {
  if ((feet1==105) | (feet2==105))  // if standing on an elevator, move it up
     upelev();
  else
     spy=-4;	// otherwise look up
  }
if (kbdon[1]==1)	// Pressing down
  {
  if ((feet1==105) | (feet2==105))   // and the same for down...
     downelev();
  else
     spy=+4;
 }

checkelevators(); // make sure they come back down when not standing on them

moveguys();  // move all the bad guys


wscrollwindow(spx,spy,mymap);	// update the scrolling window
wshowobjects();

wcopyscroll(30,10);
} while (kbdon[4] !=1);			// until ESC is pressed

uninstallkbd();

wendscroll();
wfreesprites(blocks);
wfreesprites(sprites);
free(mymap);
textmode(C80);
}


// see what is to the right of you
void checkright(void)
{
/*
To find out where the main character is on the map, and what is around
him/her, you need to use wgetworldblock to return what is at a certain
location on the map.

If the main character is 16x16, and is moving right:


	       --------- \
	       |       | |
	       |Block 1| | 16 pixels high
     ----------|       | |
     |   /\   ||       | /
     |   \/   |---------
     |  ----  ||       |
     |   /\   ||Block 2|
     ----------|       |
     Main Char.|       |
     16 pixels ---------
	high

Since you could be halfway between two blocks, it is necessary to
check two places. If you only check one, you will probably be able to
walk through walls.

Now suppose the main character was 32 pixels high.
You will need to check 3 places. The diagram would look like this:

	       --------- \
	       |Block 1| | 16 pixels high
     ----------|       | |
     |   /\   ||-------| /
     |   \/   ||Block 2|
     |  ----  ||       |
     |   /\   ||-------|
     ----------|Block 3|
     Main Char.|       |
     32 pixels ---------
	high

As you can see, it depends on how large the main character is, and
what increments he/she moves by. Try to keep your characters small,
to eliminate some of the checks needs.
*/

int j,k,l;

  j=wgetworldblock(wobject[YOU].x+16,wobject[YOU].y+1,mymap);
  k=wgetworldblock(wobject[YOU].x+16,wobject[YOU].y+15,mymap);
  if ((j>=100) | (k>=100))
    {
	j=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y+1,mymap);
	k=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y+15,mymap);
   while ((j>=100) | (k>=100)) {
   wobject[YOU].x--;
  j=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y+1,mymap);
  k=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y+15,mymap);

   }
   }
}


void checkleft(void)
{
int j,k,l;

  j=wgetworldblock(wobject[YOU].x-1,wobject[YOU].y,mymap);
  k=wgetworldblock(wobject[YOU].x-1,wobject[YOU].y+15,mymap);
  if ((j>=100) | (k>=100))
    {
  j=wgetworldblock(wobject[YOU].x,wobject[YOU].y,mymap);
  k=wgetworldblock(wobject[YOU].x,wobject[YOU].y+15,mymap);
   while ((j>=100) | (k>=100)) {
   wobject[YOU].x++;
  j=wgetworldblock(wobject[YOU].x,wobject[YOU].y,mymap);
  k=wgetworldblock(wobject[YOU].x,wobject[YOU].y+15,mymap);
   }
   }
}

void checkfeet(void)
{
int j,k;

  feet1=wgetworldblock(wobject[YOU].x,wobject[YOU].y+16,mymap);
  feet2=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y+16,mymap);
  if ((feet1<50) & (feet2<50))
    jumping=1;
    else {
   jumping=0;
   addy=0;
   j=wgetworldblock(wobject[YOU].x,wobject[YOU].y+15,mymap);
   k=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y+15,mymap);
   while ((j>=100) | (k>=100)) {
   wobject[YOU].y--;
   j=wgetworldblock(wobject[YOU].x,wobject[YOU].y+15,mymap);
   k=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y+15,mymap);
   }
   }
}

void checkhead(void)
{
int j,k;

  head1=wgetworldblock(wobject[YOU].x,wobject[YOU].y-1,mymap);
  head2=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y-1,mymap);
  if ((head1<50) & (head2<50))
    jumping=1;
    else {
   jumping=0;
   addy=0;
   j=wgetworldblock(wobject[YOU].x,wobject[YOU].y,mymap);
   k=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y,mymap);
   while ((j>=100) | (k>=100)) {
   wobject[YOU].y++;
   j=wgetworldblock(wobject[YOU].x,wobject[YOU].y,mymap);
   k=wgetworldblock(wobject[YOU].x+15,wobject[YOU].y,mymap);
   }
   }
}

// search for the elevators on the map.
void findelevators(void)
{
int i,j,k;
for (i=0; i<=mapheight; i++)
  for (j=0; j<=mapwidth; j++)
    {
	k=wgetworldblock(j*16,i*16,mymap);
	if (k==105)
	  {
	  elev[numelev].curheight=i;
	  elev[numelev].origx=j;
	  elev[numelev].origy=i;
	  elev[numelev].timer=0;

	  for (k=0; k<200; k++)
	  replace[k]=0;
	  numelev++;
	}
    }
  }

// move an elevator up
void upelev(void)
{
int ii,jj;
for (ii=0; ii<numelev; ii++)
 {
 if ( (elev[ii].origx>=(wobject[YOU].x/16)-1)
    & (elev[ii].curheight>=(wobject[YOU].y/16)-1)
    & (elev[ii].origx<=(wobject[YOU].x/16)+1)
    & (elev[ii].curheight<=(wobject[YOU].y/16)+1)
    & ((elevup==-1) | (elevup==ii))
    & (wobject[YOU].y>16))
    {
     checkhead();
     if ((head1<50) & (head2<50))
     {
     replace[elev[ii].curheight-1]=wgetworldblock(elev[ii].origx*16,(elev[ii].curheight-1)*16,mymap);
     wputworldblock(elev[ii].origx*16,elev[ii].curheight*16,104,mymap);
     wputworldblock(elev[ii].origx*16,(elev[ii].curheight-1)*16,105,mymap);
     elev[ii].curheight--;
     elevup=ii;
     wobject[YOU].y-=16;
      elev[ii].timer=10;
     }
     }
    }
}

void downelev(void)
{
int ii,jj;
for (ii=0; ii<numelev; ii++)
 {
 if ((elev[ii].origx>=(wobject[YOU].x/16)-1)
    & (elev[ii].curheight>=(wobject[YOU].y/16)-1)
    & (elev[ii].origx<=(wobject[YOU].x/16)+1)
    & (elev[ii].curheight<=(wobject[YOU].y/16)+1)
    & (elev[ii].curheight !=elev[ii].origy))
    {
     wputworldblock(elev[ii].origx*16,elev[ii].curheight*16,replace[elev[ii].curheight],mymap);
     wputworldblock(elev[ii].origx*16,(elev[ii].curheight+1)*16,105,mymap);
     elev[ii].curheight++;
     if (elev[ii].curheight==elev[ii].origy)
	 elevup=-1;
     wobject[YOU].y+=16;
     elev[ii].timer=10;
     }
    }
}

void checkelevators(void)
{
int ii;

for (ii=0; ii<numelev; ii++)
  {
  if ((elev[ii].curheight !=elev[ii].origy))
  {
  if (elev[ii].timer==0)
  {
     wputworldblock(elev[ii].origx*16,elev[ii].curheight*16,replace[elev[ii].curheight],mymap);
     wputworldblock(elev[ii].origx*16,(elev[ii].curheight+1)*16,105,mymap);
     elev[ii].curheight++;
     if (elev[ii].curheight==elev[ii].origy)
	 elevup=-1;
   elev[ii].timer=0;
  }
  else elev[ii].timer--;
  }
}
}

void moveguys(void)
{
int j,k;

for (i=0; i<=36; i++)
  {
  if ((wobject[i].on==1) &				// sprite on
      (sprites[wobject[i].num] !=NULL))		// sprite made
	{
	if ((wobject[i].x<worldx+windowmaxx) &		// and on the screen
	    (wobject[i].y<worldy+windowmaxy) &
	    (wobject[i].x+spritewidth[wobject[i].num]>worldx) &
	    (wobject[i].y+spriteheight[wobject[i].num]>worldy))
	    {
	    if (wobject[i].num<16)  // walking right
	       {
	       wobject[i].num++;
	       if (wobject[i].num>15) wobject[i].num=12; // walking animation loop
	       wobject[i].x+=3;
	       j=wgetworldblock(wobject[i].x+16,wobject[i].y+16,mymap);
	       k=wgetworldblock(wobject[i].x+16,wobject[i].y+8,mymap);
	       if ((j<50) | (k>=50)) wobject[i].num=16;
	       }
	    if (wobject[i].num>15)  // walking left
	       {
	       wobject[i].num++;
	       if (wobject[i].num>19) wobject[i].num=16; // walking animation loop
	       wobject[i].x-=3;
	       j=wgetworldblock(wobject[i].x,wobject[i].y+16,mymap);
	       k=wgetworldblock(wobject[i].x,wobject[i].y+8,mymap);
	       if ((j<50) | (k>=50)) wobject[i].num=12;
	       }
	}
  }
 }
}