#include "gridhunt.h" extern "C" int abs(int); /* Now let's define a global Monster_pointer */ Monster *Mobptr; /* General Functions */ int dice(int eyes) { return(random()%eyes+1); } int int_sqr(int a) {return a*a;} // -------------------------------------------------------------- /* Functions for the class Coor * Constructor I: just initialize */ Coor::Coor(int a,int b){x=a;y=b;} Coor ERROR_COORD(-1,-1); void Coor::print() { cout << "X: "<< x << " Y: " << y << "\n"; } int Coor::operator==(Coor& arg2) { return (x==arg2.x && y==arg2.y); } // ------------------------------------------------------------------ /* Functions for the class Mobile * Constructor I: just initialize * Constructor II: initialize with a name */ Mobile::Mobile(char* mob_name) { cds.x=0;cds.y=0; // in the grid, if named !! strncpy(name,mob_name,40); } void Mobile::reset() { if(cds==ERROR_COORD) return; cds.x=0; cds.y=0; } /* Private Functions */ int Mobile::do_move(int x,int y) { int test=cds.x+x; if(test<0 || test>=GRIDX) return FALSE; test=cds.y+y; if(test<0 || test>=GRIDY) return FALSE; cds.x+=x; cds.y+=y; return TRUE; } /* Name the puppy, set puppy's position */ void Mobile::set_name(char *mob_name) { if(mob_name) strncpy(name,mob_name,40); } char *Mobile::get_name() { return name; } void Mobile::set_pos(int x, int y) { /* This isn't very beautiful but it works. better: error */ if(x>=GRIDX || x<0) return; if(y>=GRIDX || y<0) return; cds.x=x; cds.y=y; } /* Returns the position in COORDINATES !!!!! */ Coor Mobile::my_pos() {return cds;} /* Movement: Directions.... * 8 1 2 * \|/ * 7-*-3 * /|\ * 6 5 4 */ int Mobile::move(int dir) { int ret; switch(dir) // number between 1..8 { case 1: ret=do_move( 0, 1); break; case 2: ret=do_move( 1, 1); break; case 3: ret=do_move( 1, 0); break; case 4: ret=do_move( 1,-1); break; case 5: ret=do_move( 0,-1); break; case 6: ret=do_move(-1,-1); break; case 7: ret=do_move(-1, 0); break; case 8: ret=do_move(-1, 1); break; default: // no valid direction cerr << "invalid movement direction:" << dir << endl; return FALSE; break; } return ret /* True False */; } /* Give the distance function to both Monster & Player * Returns the distance in Moves !!!! */ int Mobile::distance(const Mobile& mobile ) { int dx,dy; dx=abs(mobile.cds.x-cds.x); dy=abs(mobile.cds.y-cds.y); return (dx<=dy?dy:dx); } void Mobile::print_pos() { cout << form("%-15s: x=%4d, y=%4d\n", name, cds.x, cds.y); } /* Function for the Class MONSTER */ /* Monster::move overloads Mobile::move * Probabilities: * 1d12 : 1-4 (30%) Monsters stays, others: Monster moves * If monsters stays 10% Probability that monster teleports * 30%(stay)*10%(teleport)==3% (for teleport) */ int Monster::move() { /* returns TRUE if moved in a way, else FALSE */ int move, teleport, ret, dir; move=((dice(12)>=4) ? TRUE : FALSE); /* 60% */ teleport=((dice(100)<=10) ? TRUE : FALSE); /* 10% */ if(move==TRUE) { /* first move */ do{ ret=Mobile::move(dice(8)); }while(ret==FALSE); if(dice(5)==1) do{ ret=Mobile::move(dice(8)); }while(ret==FALSE); } else { /* chance for teleport */ if(teleport==TRUE) { Mobile::teleport(); ret=TRUE; } } return ret; } void Mobile::teleport() { set_pos((random())%GRIDX,(random())%GRIDY); } /* Function for the Class PLAYER */ /* Player Move overloads the Mobile::move function * */ Player::Player(char *name):Mobile(name) {turns=2; wins=a_pos=a_dis=a_mov=c_pos=c_dis=c_mov=0;} void Player::tick(){turns=2;} int Player::teleport() { if (turns<2) { return FALSE; } else { Mobile::teleport(); turns-=2; } return TRUE; } Coor Player::monster_pos() { /* only if the player has 2 turns */ if(turns < 2) return ERROR_COORD; turns-=2; c_pos++; return Mobptr->Mobile::my_pos(); } int Player::monster_dist() { /* only if the player has 2 turns */ if(turns < 1) return -1; turns--; c_dis++; return Mobile::distance(*Mobptr); } Coor Player::player_pos(const Player& plr) { return plr.Mobile::my_pos(); } int Player::player_dist(const Player& plr) { return Mobile::distance(plr); } int Player::move(int dir) /* directions as in monster_move */ /* returns TRUE if Move was done correctly, otherwise false */ { int ret=FALSE; if(turns < 1) return ret; ret=Mobile::move(dir); if(ret==TRUE) { turns--; c_mov++; } return ret; } void Player::reset() { a_pos=(a_pos+c_pos)/(1+1*(a_pos>0)); a_dis=(a_dis+c_dis)/(1+1*(a_dis>0)); a_mov=(a_mov+c_mov)/(1+1*(a_mov>0)); c_mov=c_pos=c_dis=0; Mobile::reset(); } /* prints the statistics of the calls !! flag== TRUE prints ava_stats * FALSE prints current_stats */ void Player::print_stats(int flag) { int *mov=&c_mov,*dis=&c_dis,*pos=&c_pos; char text[20]="cur."; if(flag) { mov=&a_mov; dis=&a_dis; pos=&a_pos; strcpy(text,"avg."); } cout << form("%-15s %4s Stats: Mov: %4d Dis: %4d Pos: %4d Wins: %4d\n", Mobile::get_name(), text, *mov, *dis, *pos, wins); }