*/
Love this site? Hate it? Leave us some comments.
*/

View SRC\BOBOLI.C

BOBOLI THE MIGHTY KNIGHT Networked Medieval Conflict

Submitted By: Unknown
Rating: starstarstar (Rate It)


/*
  BOBOLI main game executable
  By Mike Hommel
  CSC 404
  compile with DJGPP v2
*/

#include "mgraph.h"
#include "umk.h"
#include "timer.h"
#include "mkey.h"
#include "mfont.h"
#include "boboli.h"
#include "guys.h"
#include <stdio.h>
#include "com.h"

projectile prj[maxprjctls];
displayrec disp[maxdisplay];
genrec gen[maxgen];
umkset stuff,guypix[numtypes],prjpix,objpix;
scrntype scrn,scrn2;
byte *backgd[2];
byte curpage=0;
byte anim=0;
tileset tiles;
paltype gamepal;
colmat dark;
maprec map;
byte quit=0;
short scrx,scry;
creature guy[maxguys];
playerrec player[numplayers];
centerray guyctr[numtypes],prjctr,objctr;
word randseed1=20; /* for my not-quite-random number generator */
word randseed2=75;
word randnum,randrange;
rect validscreen={0,0,199,199};
byte player_num; /* which of the players is on this computer */
byte twoplayer=1;
byte numcreatures=0;

void titles(void)
{
  paltype p;
  memset(p,0,768);
  setpal(p);
  loadPCX("pcx\\title.pcx",p,screen);
  fade_in(0,0,0,p);
  print(318-14*6,192,244,0,"PRESS A KEY...",screen);
  while((keystate(_Q)!=pressed)&&(keystate(_A)!=pressed)&&
     (keystate(_S)!=pressed)&&(keystate(_W)!=pressed));
  clear(0,screen);
}

byte intersect(rect s,rect d)
{
  return ((s.x<=d.x2)&&(s.x2>=d.x)&&(s.y<=d.y2)&&
          (s.y2>=d.y)&&(s.x!=s.x2)&&(s.y!=s.y2)&&
          (d.x!=d.x2)&&(d.y!=d.y2));
}

word random(word range)
{
  randrange=range;
  asm volatile ("pusha
       movw _randseed2,%ax
       movw _randseed1,%bx
       movw %ax,%si
       movw %bx,%di
       movb %ah,%dl
       movb %al,%ah
       movb %bh,%al
       movb %bl,%bh
       xorb %bl,%bl
       rcrb $1,%dl
       rcrw $1,%ax
       rcrw $1,%bx
       addw %di,%bx
       adcw %si,%ax
       addw $0x62e9,%bx
       adcw $0x3619,%ax
       movw %bx,_randseed2
       movw %ax,_randseed1
       xorw %dx,%dx
       movw _randrange,%cx
       divw %cx
       movw %dx,_randnum
       popa"
);
  return randnum;
}

void gamedelay(void)
{
  asm volatile ("pushw %ax
  1:
       movb _timetick,%al
       cmpb $0,%al
       jz  1b
       popw %ax
       "
);
  timetick=0;
  waitretrace();
}

void loadctr(char *name,centerray c)
{
  FILE *f;
  f=fopen(name,"rb");
  fread(c,1,sizeof(centerray),f);
  fclose(f);
}

void loadtiles(char *name,tileset t)
{
  short i,j,k,x,y;
  paltype p;
  loadPCX(name,p,scrn);
  x=0; y=0;
  for(i=0;i<128;i++) {
    for(j=0;j<16;j++)
      for(k=0;k<16;k++)
        t[i][j+k*16]=scrn[x+j+(y+k)*320];
    x+=16;
    if(x>319) {
      x=0;
      y+=16;
    }
  }
}

void loadmap(void)
{
  FILE *f;
  f=fopen("temp.map","rb");
  fread(map,sizeof(maprec),1,f);
  fread(gen,sizeof(genrec)*maxgen,1,f);
  fclose(f);
}

void get_input(byte wh)
{
  if(guy[player[wh].who].hp>0) {
    player[wh].command=((keystate(Up)==pressed)||(keystate(Up)==held))*cmd_up+
                       ((keystate(Down)==pressed)||(keystate(Down)==held))*cmd_dn+
                       ((keystate(Left)==pressed)||(keystate(Left)==held))*cmd_lf+
                       ((keystate(Right)==pressed)||(keystate(Right)==held))*cmd_rt+
                       ((keystate(_Q)==pressed)||(keystate(_Q)==held))*cmd_at+
                       (keystate(_A)==pressed)*cmd_drop+
                       (keystate(_S)==pressed)*cmd_next+
                       (keystate(_W)==pressed)*cmd_use;
  } else player[wh].command=0;
}

byte addcreature(byte kind,short x,short y,byte dir,byte control)
{
  byte i=0;
  while((i<maxguys)&&(guy[i].kind!=nobody)) i++;
  if(i==maxguys) return 255;
  numcreatures++;
  guy[i].kind=kind;
  guy[i].hp=cd[kind].maxhp;
  guy[i].x=x;
  guy[i].y=y;
  guy[i].z=0;
  guy[i].dz=0;
  guy[i].dir=dir;
  guy[i].timer=0;
  guy[i].doing=do_stand;
  guy[i].frame=0;
  guy[i].control=control;
  guy[i].nearfoe=255;
  guy[i].friend=255;
  guy[i].state=0;
  return i;
}

byte addprjctl(byte kind,short x,short y,byte z,byte dir,byte launcher,byte lguy)
{
  byte i=0;
  while((i<maxprjctls)&&(prj[i].kind!=pr_none)) i++;
  if(i==maxprjctls) return 255;
  prj[i].kind=kind;
  prj[i].x=x;
  prj[i].y=y;
  prj[i].z=z;
  prj[i].dir=dir%4;
  prj[i].launchguy=lguy;
  switch(kind) {
    case pr_spark: prj[i].timer=6;
                   prj[i].dx=2-random(5);
                   prj[i].dy=2-random(5);
                   prj[i].dz=0;
                   if(dir==1) prj[i].dz=1;
                   break;
    case pr_golem: prj[i].timer=14;
                   prj[i].dx=0;
                   prj[i].dy=0;
                   prj[i].dz=0;
                   break;
    case pr_flower: prj[i].timer=26;
                   prj[i].dx=0;
                   prj[i].dy=0;
                   prj[i].dz=0;
                   break;
    case pr_shield: prj[i].timer=1;
                    prj[i].dx=0;
                    prj[i].dy=0;
                    prj[i].dz=0;
                    break;
    case pr_smoke: prj[i].timer=12;
                   prj[i].dx=0;
                   prj[i].dy=0;
                   prj[i].dz=2;
                   break;
    case pr_splash: prj[i].timer=35;
                    prj[i].dx=0;
                    prj[i].dy=0;
                    prj[i].dz=0;
                    break;
    case pr_tornado: prj[i].timer=50;
                     prj[i].dx=2*(dir==0)-2*(dir==2);
                     prj[i].dy=2*(dir==1)-2*(dir==3);
                     prj[i].dz=0;
                     break;
    case pr_hsprk: prj[i].timer=6;
                   prj[i].dx=2-random(5);
                   prj[i].dy=2-random(5);
                   prj[i].dz=0;
                   if(dir==1) prj[i].dz=1;
                   break;
    case pr_arrow: prj[i].timer=0;
                   prj[i].dx=7*(prj[i].dir==0)-7*(prj[i].dir==2);
                   prj[i].dy=7*(prj[i].dir==1)-7*(prj[i].dir==3);
                   prj[i].dz=0;
                   if((dir>3)&&(dir<8)) {
                     prj[i].dx+=3*(prj[i].dir==3)-3*(prj[i].dir==1);
                     prj[i].dy+=3*(prj[i].dir==0)-3*(prj[i].dir==2);
                   }
                   if(dir>7) {
                     prj[i].dx+=3*(prj[i].dir==1)-3*(prj[i].dir==3);
                     prj[i].dy+=3*(prj[i].dir==2)-3*(prj[i].dir==0);
                   }
                   break;
    case pr_fball: prj[i].timer=5;
                   prj[i].dx=5*(dir==0)-5*(dir==2);
                   prj[i].dy=5*(dir==1)-5*(dir==3);
                   prj[i].dz=0;
                   break;
    case pr_burst: prj[i].timer=8;
                   prj[i].dx=0;
                   prj[i].dy=0;
                   prj[i].dz=0;
                   break;
    case pr_homing: prj[i].timer=35*5;
                    prj[i].dx=0;
                    prj[i].dy=0;
                    prj[i].dz=0;
                    break;
    case pr_skull: prj[i].timer=70;
                   prj[i].dx=(dir==0)-(dir==2);
                   prj[i].dy=(dir==1)-(dir==3);
                   prj[i].dz=0;
                   break;
    case pr_brightspot: prj[i].timer=10+(z>0)*4;
                        prj[i].dx=0;
                        prj[i].dy=0;
                        prj[i].dz=0;
                        prj[i].z=0;
                        break;
    case pr_slime: prj[i].timer=0;
                   prj[i].dx=4*(dir==0)-4*(dir==2);
                   prj[i].dy=4*(dir==1)-4*(dir==3);
                   prj[i].dz=3;
                   break;
    case pr_splat: prj[i].timer=6;
                   prj[i].dx=0;
                   prj[i].dy=0;
                   prj[i].dz=0;
                   break;
  }
  prj[i].launcher=launcher;
  return i;
}


void init_player(byte wh)
{
  byte i;
  strcpy(player[wh].name,"JAMUL");
  player[wh].color=19+wh*16;
  player[wh].command=0;
  player[wh].who=addcreature(boboli,32+wh*48+8,32,1,wh);
  player[wh].homex=(32+wh*48)/16;
  player[wh].homey=2;
  map[player[wh].homex+player[wh].homey*mapwidth].object=ob_genrtr;
  for(i=0;i<maxgen;i++) if(gen[i].kind==gn_none) {
    gen[i].kind=gn_boboli;
    gen[i].x=player[wh].homex;
    gen[i].y=player[wh].homey;
    gen[i].hp=1;
    gen[i].frame=1;
    i=maxgen;
  }
  guy[player[wh].who].state|=st_invis;
  guy[player[wh].who].state|=st_invinc;
  guy[player[wh].who].hp=0;
  guy[player[wh].who].friend=wh;
  player[wh].victimkind=255;
  player[wh].strength=1;
  player[wh].speed=1;
  player[wh].intellect=1;
  player[wh].armor=1;
  player[wh].skill=0;
  player[wh].magictimer=1;
  player[wh].selfhptimer=1;
  player[wh].magic=0;
  player[wh].selfhp=0;
  player[wh].realmagic=0;
  player[wh].realselfhp=0;
  player[wh].using=0;
  player[wh].messtimer=0;
  strcpy(player[wh].message,player[wh].name);
  player[wh].inv[0]=it_xbow;
  player[wh].invistimer=0;
  player[wh].invinctimer=0;
  for(i=1;i<6;i++)
    player[wh].inv[i]=0;
}

void init_boboli(void)
{
  byte i;
  __djgpp_nearptr_enable();
  initmg();
  timer_init(FRAMERATE);
  kb_init();
  font_init("misc\\little.fnt");
  gmode(0x13);
  scrn=(scrntype)malloc(64000);
  scrn2=(scrntype)malloc(64000);
  backgd[0]=(byte *)malloc(backgdwidth*backgdheight);
  backgd[1]=(byte *)malloc(backgdwidth*backgdheight);
  mat_load("misc\\dark.mat",dark);
  umk_load("umks\\stuff.umk",stuff);
  umk_load("umks\\boboli.umk",guypix[0]);
  umk_load("umks\\bonehead.umk",guypix[1]);
  umk_load("umks\\glob.umk",guypix[2]);
  umk_load("umks\\golem.umk",guypix[3]);
  umk_load("umks\\orc.umk",guypix[4]);
  umk_load("umks\\mage.umk",guypix[5]);
  umk_load("umks\\prjctls.umk",prjpix);
  umk_load("umks\\objects.umk",objpix);
  loadctr("ctr\\boboli.ctr",guyctr[0]);
  loadctr("ctr\\bonehead.ctr",guyctr[1]);
  loadctr("ctr\\glob.ctr",guyctr[2]);
  loadctr("ctr\\golem.ctr",guyctr[3]);
  loadctr("ctr\\orc.ctr",guyctr[4]);
  loadctr("ctr\\mage.ctr",guyctr[5]);
  loadctr("ctr\\prjctls.ctr",prjctr);
  loadctr("ctr\\objects.ctr",objctr);
  loadtiles("pcx\\tiles.pcx",tiles);
  loadPCX("pcx\\main.pcx",gamepal,scrn2);
  titles();
  setpal(gamepal);
  for(i=0;i<maxguys;i++) guy[i].kind=nobody;
  for(i=0;i<maxprjctls;i++) prj[i].kind=pr_none;
  loadmap();
  init_player(0);
  if(twoplayer) init_player(1);
  addcreature(mage,60*16,54*16,1,255);
}

void exit_boboli(void)
{
  kb_exit();
  timer_exit();
  gmode(0x3);
  umk_free(stuff);
  umk_free(prjpix);
  umk_free(objpix);
  umk_free(guypix[0]);
  umk_free(guypix[1]);
  umk_free(guypix[2]);
  free(scrn);
  free(scrn2);
  free(backgd[0]);
  free(backgd[1]);
  while(kbhit()) getch();
  __djgpp_nearptr_disable();
}

byte calc_shadows(byte x,byte y)
{
  byte v;
  if(map[x+y*mapwidth].floor>63) return 0; /* no shadows on walls */
  if((map[x+y*mapwidth].floor==1)||(map[x+y*mapwidth].floor==2))
    return 0; /* no shadows on doors */
  if(x==0) {
    if(y==0) return 6;
    else if(map[x+(y-1)*mapwidth].floor>63) return 6;
    else return 2;
  }
  if(y==0) {
    if(map[x-1+y*mapwidth].floor>63) return 6;
    else return 4;
  }
  if(map[x-1+y*mapwidth].floor>63) {
    if(map[x+(y-1)*mapwidth].floor>63) return 6;
    if(map[x-1+(y-1)*mapwidth].floor>63) return 2;
    else return 1;
  }
  if(map[x+(y-1)*mapwidth].floor>63) {
    if(map[x-1+(y-1)*mapwidth].floor>63) return 4;
    else return 5;
  }
  if(map[x-1+(y-1)*mapwidth].floor>63) return 3;
  return 0;
}

long tilesrc,tiledst,tilecaddr;
void tile_shadow(byte x,byte y,colmat c,umkrec u,byte *scr)
{
  tilesrc=(long)u.img;
  tiledst=(long)(scr+x+y*backgdwidth);
  tilecaddr=(long)c;
  asm("pusha
       push %ds
       pop  %es
       movl _tilesrc,%esi
       movl _tiledst,%edi
       movb $16,%dl
       movb $16,%dh
       xorl %eax,%eax
       movl _tilecaddr,%ebx
tshloop1:
       movb %ds:(%esi),%al
       incl %esi
       cmpb $0,%al
       jnz  tshnonzero
       movb %ds:(%esi),%al
       incl %esi
       addl %eax,%edi
       subb %al,%dl
       jnz  tshloop1
       jmp tshlinedone
tshnonzero:
       movb %es:(%edi),%al
       movb %ds:(%ebx,%eax),%al
       movb %al,%es:(%edi)
       incl %edi
       decb %dl
       jnz  tshloop1
tshlinedone:
       decb %dh
       jz   tshdone
       addl $240,%edi
       movb $16,%dl
       jmp  tshloop1
tshdone:
       popa"
);
}

void draw_tile(byte x,byte y,tilerec t,byte *scr)
{
  register byte i;
  for(i=0;i<16;i++) {
    memcpy(&(scr[x+y*backgdwidth]),&(tiles[t.floor][i*16]),16);
    y++;
  }
  y-=16;
  if(t.shadow>0)
    tile_shadow(x,y,dark,stuff[t.shadow-1],scr);
}

void draw_map(short x,short y)
{
  byte i,j;
  byte sx,sy;
  sy=16-(y%16);
  for(j=(byte)(y/16);j<(byte)(y/16+14);j++) {
    sx=16-(x%16);
    for(i=(byte)(x/16);i<(byte)(x/16+14);i++) {
      draw_tile(sx,sy,map[i+j*mapwidth],backgd[0]);
      sx+=16;
    }
    sy+=16;
  }
  for(i=16;i<216;i++)
    memcpy(&(scrn[(i-16)*320]),&(backgd[0][16+i*backgdwidth]),200);
  curpage=0;
}

void scrollscr(short dx,short dy,scrntype src,scrntype dst)
{
  long sofs,dofs,amt;
  amt=((256-abs(dx))>>2)+(255-abs(dy))*64+1;
  sofs=(long)src+(dy>0)*(dy*256);
  dofs=(long)dst+(dy<0)*(-dy*256);
  sofs+=(dx>0)*dx;
  dofs+=(dx<0)*(-dx);
  asm("pusha
       pushw %%ds
       popw  %%es
       movl  %0,%%esi
       movl  %1,%%edi
       movl  %2,%%ecx
       rep;  movsl
       popa"
::"m" (sofs),"m" (dofs),"m" (amt));
}

void update_inv(void)
{
  short i,x=212,y=61;
  xfer(211,60,278+32+1,94+32+1,scrn2,scrn);
  for(i=0;i<6;i++) {
    if(player[player_num].inv[i]>it_none)
      umk_draw(x,y,stuff[7+player[player_num].inv[i]],scrn);
    if(player[player_num].using==i) umk_draw(x-1,y-1,stuff[8],scrn);
    x+=33;
    if(x>278) {
      x=212;
      y+=33;
    }
  }
}

void update_stats(void)
{
  xfer(208,130,208+49,154+2,scrn2,scrn);
  box(208,130,207+player[player_num].strength,132,54,scrn);
  box(208,136,207+player[player_num].speed,138,54,scrn);
  box(208,142,207+player[player_num].intellect,144,54,scrn);
  box(208,148,207+player[player_num].armor,150,54,scrn);
  if(player[player_num].skill>0)
    box(208,154,207+(player[player_num].skill*50)/player[player_num].skillmax,156,54,scrn);
}

void data_display(void)
{
  xfer(211,28,211+99,28+11,scrn2,scrn);
  xfer(211,45,211+99,45+11,scrn2,scrn);
  if(player[player_num].selfhp>player[player_num].realselfhp)
    player[player_num].selfhp--;
  if(player[player_num].selfhp<player[player_num].realselfhp)
    player[player_num].selfhp++;
  if(player[player_num].selfhp>0) {
    box(211,28,210+player[player_num].selfhp,28,42,scrn);
    box(211,29,210+player[player_num].selfhp,29,43,scrn);
    box(211,30,210+player[player_num].selfhp,37,39,scrn);
    box(211,38,210+player[player_num].selfhp,38,37,scrn);
    box(211,39,210+player[player_num].selfhp,39,36,scrn);
  }
  if(player[player_num].magic>player[player_num].realmagic)
    player[player_num].magic--;
  if(player[player_num].magic<player[player_num].realmagic)
    player[player_num].magic++;
  if(player[player_num].magic>0) {
    box(211,45,210+player[player_num].magic,45,24,scrn);
    box(211,46,210+player[player_num].magic,46,26,scrn);
    box(211,47,210+player[player_num].magic,54,23,scrn);
    box(211,55,210+player[player_num].magic,55,21,scrn);
    box(211,56,210+player[player_num].magic,56,20,scrn);
  }
  xfer(205,190,315,196,scrn2,scrn);
  if(player[player_num].messtimer==0) {
    print(206,191,15,8,player[player_num].message,scrn);
  } else {
    player[player_num].messtimer--;
    print(206,191,32+15-abs(15-player[player_num].messtimer/2),0,
          player[player_num].message,scrn);
    if(--player[player_num].messtimer==0) {
      strcpy(player[player_num].message,player[player_num].name);
    }
  }
}

void scrollmap(char dx,char dy)
{
  byte i,j;
  byte sx,sy;
  short osx,osy;
  osx=scrx; osy=scry;
  scrx+=dx; scry+=dy;
  if(scrx<0) scrx=0;
  if(scrx>mapwidth*16-200-16) scrx=mapwidth*16-200-16;
  if(scry<0) scry=0;
  if(scry>mapheight*16-200-16) scry=mapheight*16-200-16;
  dx=scrx-osx; dy=scry-osy;
  scrollscr(dx,dy,backgd[curpage],backgd[1-curpage