/* Copyright (C) 1995-2002 FSGames. Ported by Sean Ford and Yan Shosh * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // // Stats.cpp // #include "graph.h" #include "stats.h" // for bit flags, etc. #include #define CHECK_STEP_SIZE 1 // (controller->stepsize) // was 1 // COMMAND declarations defined at bottom statistics::statistics(walker * someguy) { short i; if (someguy) controller = someguy; else { controller = NULL; printf("made a stats with no controller!\n"); } hitpoints = max_hitpoints = 10; magicpoints = max_magicpoints = 50; level = 1; armor = 0; // no default armor max_heal_delay = current_heal_delay = 1000; // default of 50 cycles / hitpoint max_magic_delay = current_magic_delay = 1000; magic_per_round = 0; //default to not regenerating magic heal_per_round = 0; //default to not regenerating hitpoints bit_flags = 0; // clear all the bit flags frozen_delay = 0; // start out able to move :) for (i=0; i < 5; i++) special_cost[i] = 0; // low default special ability cost in magicpoints weapon_cost = 0; delete_me = 0; // AI finding routine values .. last_distance = current_distance = 15000; // set head and end to null commandlist = NULL; endlist = NULL; old_order = controller->order; old_family= controller->family; name[0] = 0; // set to null string } statistics::~statistics() { command *here; here = commandlist; while(here) { commandlist = here; here = here->next; delete commandlist; commandlist = NULL; } controller = NULL; delete_me = 1; } void statistics::clear_command() { command *here; here = commandlist; while(here) { commandlist = here; here = here->next; delete commandlist; commandlist = NULL; } commandlist = NULL; endlist = NULL; // Make sure our weapon type is restored to normal .. controller->current_weapon = controller->default_weapon; // Make sure we're back to our real team if (controller->real_team_num != 255) { controller->team_num = controller->real_team_num; controller->real_team_num = 255; } controller->leader = NULL; } void statistics::add_command(short whatcommand, short iterations, short info1, short info2) { if (whatcommand == COMMAND_DIE) { delete_me = 1; return; } if (whatcommand == COMMAND_FOLLOW) { printf("following\n"); } // Add command to end of list if (endlist) { endlist->next = new command; endlist = endlist->next; } else { endlist = new command; } // Connect to beginning of list if list was empty if (!commandlist) commandlist = endlist; if (whatcommand == COMMAND_WALK) { if (info1 > 1) info1 = 1; if (info1 < -1) info1 = -1; if (info2 > 1) info2 = 1; if (info2 < -1) info2 = -1; if (!info1 && !info2) info1 = info2 = 1; } endlist->com1 = info1; endlist->com2 = info2; endlist->commandtype = whatcommand; endlist->commandcount = iterations; // endlist->next = NULL; } void statistics::force_command(short whatcommand, short iterations, short info1, short info2) { command *here; // Add command to start of list if (commandlist) { here = new command; here->next = commandlist; commandlist = here; } else { commandlist = new command; } if (whatcommand == COMMAND_WALK) { if (info1 > 1) info1 = 1; if (info1 < -1) info1 = -1; if (info2 > 1) info2 = 1; if (info2 < -1) info2 = -1; if (!info1 && !info2) info1 = info2 = 1; } commandlist->com1 = info1; commandlist->com2 = info2; commandlist->commandtype = whatcommand; commandlist->commandcount = iterations; // commandlist->next = NULL; } // try_command will only set a command if there is // none in the queue short statistics::try_command(short whatcommand, short iterations) { if (whatcommand == COMMAND_RANDOM_WALK) return try_command(COMMAND_WALK, iterations, (short) (random(3)-1), (short) (random(3)-1)); else return try_command(whatcommand, iterations, 0, 0); } short statistics::try_command(short whatcommand, short iterations, short info1, short info2) { add_command(whatcommand, iterations, info1, info2); return 0; } void statistics::set_command(short whatcommand, short iterations) { if (whatcommand == COMMAND_RANDOM_WALK) set_command(COMMAND_WALK, iterations, (short) (random(3)-1), (short) (random(3)-1)); else set_command(whatcommand, iterations, 0, 0); } void statistics::set_command(short whatcommand, short iterations, short info1, short info2) { if (whatcommand == COMMAND_DIE) printf("BLLLLLLLLLLLLLAAAAAAAAAAHHHHHHH!\n"); force_command(whatcommand, iterations, info1, info2); } // Do the current command short statistics::do_command() { command *here; short commandtype, commandcount, com1, com2; short i; // short ret1, ret2, ret3; //old code walker * target; short deltax, deltay; long distance; static short newx, newy; #ifdef PROFILING profiler docommprofiler("stats::do_command"); #endif //if (!controller || controller->dead) if (!controller) // allow dead controllers for now { printf("STATS:DO_COM: No controller!\n"); wait_for_key(SDLK_z); return 0; } // Get next command; if (commandlist) { commandtype = commandlist->commandtype; commandcount = commandlist->commandcount--; com1 = commandlist->com1; com2 = commandlist->com2; } else return 0; if (commandcount < 2) // Last iteration! { here = commandlist; commandlist = commandlist->next; if (endlist == here) endlist = NULL; delete here; here = NULL; } switch (commandtype) { case COMMAND_WALK: //if (controller->query_order() == ORDER_LIVING) //{ controller->walkstep(com1, com2); //} break; case COMMAND_FIRE: if (!(controller->query_order() == ORDER_LIVING)) { printf("commanding a non-living to fire?"); break; } if (!controller->fire_check(com1,com2)) { commandcount = 0; return 0; } controller->init_fire(com1, com2); break; case COMMAND_DIE: // debugging, not currently used if (!controller->dead) printf("Trying to make a living ob die!\n"); if (commandcount < 2) // then delete us .. delete_me = 1; break; case COMMAND_FOLLOW: // follow the leader if (controller->foe) // if we have foe, don't follow this round { commandcount = 0; controller->leader = NULL; return 0; } if (!controller->leader) { if (controller->screenp->numviews == 1) controller->leader = controller->screenp->viewob[0]->control; else { if (controller->screenp->viewob[0]->control->yo_delay) controller->leader = controller->screenp->viewob[0]->control; else if (controller->screenp->viewob[1]->control->yo_delay) controller->leader = controller->screenp->viewob[1]->control; else { commandcount = 0; controller->leader = NULL; return 0; } } } if (controller->leader) { distance = controller->distance_to_ob(controller->leader); if (distance < 60) { //controller->leader = NULL; return 1; // don't get too close } newx = (short) (controller->leader->xpos - controller->xpos); // total horizontal distance.. newy = (short) (controller->leader->ypos - controller->ypos); if (abs(newx) > abs(3*newy)) newy = 0; if (abs(newy) > abs(3*newx)) newx = 0; if (newx) // If it's not 0, then get newx = (short) (newx / abs(newx)); // the normal of it.. if (newy) newy = (short) (newy / abs(newy)); } // end of if we had a foe .. controller->walkstep(newx, newy); if (commandcount < 2) controller->leader = NULL; break; case COMMAND_QUICK_FIRE: controller->walkstep(com1, com2); controller->fire(); break; case COMMAND_MULTIDO: // Lets you do commands in one round for(i=0;iquery_order() == ORDER_LIVING) { controller->walkstep(com1, com2); controller->walkstep(com1, com2); controller->walkstep(com1, com2); if (controller->collide_ob) // We hit someone { target = controller->collide_ob; controller->attack(target); target->stats->clear_command(); // A violent shove... we can't call shove since we // made shove unable to shove enemies. target->stats->force_command(COMMAND_WALK, 4,com1,com2 ); } } break; case COMMAND_SET_WEAPON: // set weapon to specified type controller->current_weapon = com1; break; case COMMAND_RESET_WEAPON: // reset weapon to default type controller->current_weapon = controller->default_weapon; break; case COMMAND_SEARCH: // use right-hand rule to find foe if (controller->foe && !controller->foe->dead) walk_to_foe(); else // stop trying to walk to this foe commandcount = 0; break; case COMMAND_RIGHT_WALK: // right-hand-walk ONLY if (controller->foe) { distance = controller->distance_to_ob(controller->foe); if (distance > 120 && distance < 240) right_walk(); else if (!direct_walk()) right_walk(); } break; case COMMAND_ATTACK: // attack a nearby, set foe if (!controller->foe || controller->foe->dead) { commandcount = 0; return 1; } // Try to walk toward foe, and/or attack .. deltax = (short) (controller->foe->xpos - controller->xpos); deltay = (short) (controller->foe->ypos - controller->ypos); if (abs(deltax) > abs(3*deltay)) deltay = 0; if (abs(deltay) > abs(3*deltax)) deltax = 0; if (deltax) deltax /= abs(deltax); if (deltay) deltay /= abs(deltay); if (!controller->fire_check(deltax,deltay)) controller->walkstep(deltax, deltay); else // (controller->fire_check(deltax, deltay)) { force_command(COMMAND_FIRE,(short) random(5),deltax,deltay); controller->init_fire(deltax,deltay); } break; case COMMAND_UNCHARM: /* if (commandcount > 1) { add_command(COMMAND_UNCHARM, commandcount-1, 0, 0); commandcount = 1; } else if (controller->real_team_num != 255) { controller->team_num = controller->real_team_num; controller->real_team_num = 255; } */ break; // end of uncharm case default: break; } commandcount--; // reduce # of times left return 1; } // Determines what to do when we're hit by 'who' // 'controller' is our parent walker object void statistics::hit_response(walker *who) { long distance, i; short myfamily; long deltax, deltay; walker *foe; // who is attacking us? long possible_specials[NUM_SPECIALS]; long threshold; // for hitpoint 'running away' oblink *newlist; // for calling for help short howmany; if (!who || !controller) return; if (who->dead || controller->dead) return; if (controller->query_act_type() == ACT_CONTROL) return; if (controller->query_order() != ORDER_LIVING) return; // Set quick-reference values .. myfamily = controller->query_family(); if (who->query_order() == ORDER_WEAPON && who->owner) foe = who->owner; else foe = who; // Determine which specials we can do (by level and sp) .. for (i=0; i < NUM_SPECIALS; i++) // first initialize to CAN'T possible_specials[i] = 0; for (i=0; i <= (level+2)/3; i++) // for all our 'possibles' by level if ( (i < NUM_SPECIALS) && (magicpoints >= special_cost[i]) ) possible_specials[i] = 1; // then we can do it. switch (myfamily) { case FAMILY_MAGE: if (controller->myguy) // are we a player's character? threshold = (3 * max_hitpoints)/5; // then flee at 60% else // we're an enemy, so be braver :> threshold = (3 * max_hitpoints)/8; // flee at 3/8 if ( (hitpoints < threshold) && possible_specials[1] ) { // Clear old command .. // clear_command(); // teleport controller->current_special = 1; // teleport to safety controller->shifter_down = 0; // TELEPORT, not other controller->busy = 0; // force-allow us to special controller->special(); } else { if (controller->foe != foe) // we're hit by a new enemy { controller->foe = foe; foe->foe = controller; last_distance = current_distance = 15000; } } break; case FAMILY_ARCHMAGE: controller->busy = 0; // yes, this is a cheat.. if (controller->myguy) // are we a player's character? threshold = (3 * max_hitpoints)/5; // then flee at 60% else // we're an enemy, so be braver :> threshold = (3 * max_hitpoints)/8; // flee at 3/8 if ( (hitpoints < threshold) && possible_specials[1] && random(3) ) { // teleport controller->current_special = 1; // teleport to safety controller->shifter_down = 0; controller->busy = 0; // force-allow us to special controller->special(); } else // find out how many foes are around us, etc... { if (controller->foe != foe) // we're hit by a new enemy { controller->foe = foe; foe->foe = controller; last_distance = current_distance = 15000; } newlist = myscreen->find_foes_in_range(myscreen->oblist, 200, &howmany, controller); // Delete the list to save memory, not needed now /* This clean-up code is broken .. why? <- Zardus says "Because you're trying to delete an object that's in use! DUH!" Zardus then adds "sorry about that. fixing 200000 of these leaks in walker.cpp makes one a bit cranky. here, you can use my delete_list function." if (howmany && newlist) { here = newlist->next; while (here) { delete newlist; newlist = here; here = here->next; } delete newlist; } */ delete_list(newlist); if (howmany) // foes within range? { if (possible_specials[3]) // can we summon illusion? { controller->current_special = 3; if (controller->special()) return; } // end of do 3rd special if (possible_specials[2]) // heartburst, chain lightning, etc. { //if (howmany < 3) // 2 or fewer enemies, so lightning.. if (random(2)) // 50/50 now { controller->shifter_down = 1; // lightning controller->current_special = 2; if (controller->special()) { controller->shifter_down = 0; if (magicpoints >= special_cost[1]) // then leave! :) { controller->busy = 0; controller->special(); } return; } } // end of lightning controller->shifter_down = 0; controller->current_special = 2; if (controller->special()) { if (magicpoints >= special_cost[1]) // then leave! :) { controller->busy = 0; controller->special(); } return; } } // end of burst or lightning } // end of some foes in range for special attack } break; case FAMILY_ARCHER: // stay at range .. { if (!controller->foe || controller->foe != foe) { controller->foe = foe; clear_command(); last_distance = current_distance = 15000; } distance = controller->distance_to_ob(foe); if (distance < 64) // too close! { deltax = (short) (controller->xpos - foe->xpos); if (deltax) deltax = (short) (deltax / abs(deltax)); deltay = (short) (controller->ypos - foe->ypos); if (deltay) deltay = (short) (deltay / abs(deltay)); // Run away force_command(COMMAND_WALK, 8, deltax, deltay); } // end of too-close check } // end of archer case break; default: // attack our attacker // Chance of doing special .. if (controller->check_special() && !random(3) ) controller->special(); if (controller->myguy) // are we a player's character? threshold = (5 * max_hitpoints)/10; // then flee at 50% else // we're an enemy, so be braver :> threshold = (5 * max_hitpoints)/16; // flee at 5/16% if ( (hitpoints < threshold) && !controller->yo_delay) // then yell for help & run .. { yell_for_help(foe); } // end of yell for help if (controller->foe != foe) // we're attacked by a new enemy { // Clear old commands .. clear_command(); // Attack our attacker controller->foe = foe; foe->foe = controller; last_distance = current_distance = 32000; } break; } } void statistics::yell_for_help(walker *foe) { oblink *helplist, *here; short howmany; long deltax, deltay; char message[80]; controller->yo_delay += 80; helplist = controller->screenp->find_friends_in_range( controller->screenp->oblist, 160, &howmany, controller); here = helplist; while (here) { here->ob->leader = controller; if (foe != here->ob->foe) here->ob->stats->last_distance = here->ob->stats->current_distance = 32000; here->ob->foe = foe; //if (here->ob->query_act_type() != ACT_CONTROL) // here->ob->stats->force_command(COMMAND_FOLLOW, 80, 0, 0); here= here->next; } delete_list(helplist); deltax = (controller->xpos - foe->xpos); if (deltax) deltax = (deltax / abs(deltax)); deltay = (controller->ypos - foe->ypos); if (deltay) deltay = (deltay / abs(deltay)); // Run away force_command(COMMAND_WALK, 16, deltax, deltay); // Notify friends of need ... if (controller->myguy && (controller->team_num == 0) ) { sprintf(message, "%s yells for help!", controller->myguy->name); controller->screenp->do_notify(message, controller); } } short statistics::query_bit_flags(long myvalue) { return (short) (myvalue & bit_flags); } void statistics::set_bit_flags(long someflag, short newvalue) { if (newvalue) { bit_flags |= someflag; } else { bit_flags &= ~someflag; } } // Returns whether our right is blocked short statistics::right_blocked() { screen *screenp = controller->screenp; short xdelta, ydelta; short controlx = controller->xpos, controly = controller->ypos; short mystep = (short) controller->stepsize; mystep = CHECK_STEP_SIZE; switch (controller->curdir) { case FACE_UP: xdelta = mystep; ydelta = 0; break; case FACE_UP_RIGHT: xdelta = mystep; ydelta = mystep; break; case FACE_RIGHT: xdelta = 0; ydelta = mystep; break; case FACE_DOWN_RIGHT: xdelta = (short)(-mystep); ydelta = mystep; break; case FACE_DOWN: xdelta = (short)(-mystep); ydelta = 0; break; case FACE_DOWN_LEFT: xdelta = (short)(-mystep); ydelta = (short)(-mystep); break; case FACE_LEFT: xdelta = 0; ydelta = (short)(-mystep); break; case FACE_UP_LEFT: xdelta = mystep; ydelta = (short)(-mystep); break; default: xdelta = 0; ydelta = 0; break; } return !screenp->query_passable((short) (controlx + xdelta), (short) (controly + ydelta), controller); } // Returns whether our right-forward is blocked short statistics::right_forward_blocked() { screen *screenp = controller->screenp; short controlx = controller->xpos, controly = controller->ypos; short mystep = (short) controller->stepsize; mystep = CHECK_STEP_SIZE; switch (controller->curdir) { case FACE_UP: return !screenp->query_passable((short) (controlx+mystep), (short) (controly-mystep), controller); case FACE_UP_RIGHT: return !screenp->query_passable(controlx+mystep, (short) controly, controller); case FACE_RIGHT: return !screenp->query_passable((short) (controlx+mystep), (short) (controly+mystep), controller); case FACE_DOWN_RIGHT: return !screenp->query_passable((short) controlx, controly+mystep, controller); case FACE_DOWN: return !screenp->query_passable((short) (controlx-mystep), (short) (controly+mystep), controller); case FACE_DOWN_LEFT: return !screenp->query_passable((short) (controlx-mystep), (short) (controly), controller); case FACE_LEFT: return !screenp->query_passable((short) (controlx-mystep), (short) (controly-mystep), controller); case FACE_UP_LEFT: return !screenp->query_passable((short) (controlx), (short) (controly-mystep), controller); default: break; } return 0; } // Returns whether our right-back is blocked short statistics::right_back_blocked() { screen *screenp = controller->screenp; short controlx = controller->xpos, controly = controller->ypos; short mystep = (short) controller->stepsize; mystep = CHECK_STEP_SIZE; switch (controller->curdir) { case FACE_UP: return !screenp->query_passable((short) (controlx+mystep), (short) (controly+mystep), controller); case FACE_UP_RIGHT: return !screenp->query_passable(controlx, (short) (controly+mystep), controller); case FACE_RIGHT: return !screenp->query_passable((short) (controlx-mystep), (short) (controly+mystep), controller); case FACE_DOWN_RIGHT: return !screenp->query_passable((short) (controlx-mystep), controly, controller); case FACE_DOWN: return !screenp->query_passable((short) (controlx-mystep), (short) (controly-mystep), controller); case FACE_DOWN_LEFT: return !screenp->query_passable(controlx, (short) (controly-mystep), controller); case FACE_LEFT: return !screenp->query_passable((short) (controlx+mystep), (short) (controly-mystep), controller); case FACE_UP_LEFT: return !screenp->query_passable((short) (controlx+mystep), controly, controller); default: break; } return 0; } // Returns whether our front is blocked short statistics::forward_blocked() { screen *screenp = controller->screenp; short xdelta, ydelta; short controlx = controller->xpos, controly = controller->ypos; short mystep = CHECK_STEP_SIZE; switch (controller->curdir) { case FACE_UP: xdelta = 0; ydelta = (short) (-mystep); break; case FACE_UP_RIGHT: xdelta = mystep; ydelta = (short) (-mystep); break; case FACE_RIGHT: xdelta = mystep; ydelta = 0; break; case FACE_DOWN_RIGHT: xdelta = mystep; ydelta = mystep; break; case FACE_DOWN: xdelta = 0; ydelta = mystep; break; case FACE_DOWN_LEFT: xdelta = (short) (-mystep); ydelta = mystep; break; case FACE_LEFT: xdelta = (short) (-mystep); ydelta = 0; break; case FACE_UP_LEFT: xdelta = (short) (-mystep); ydelta = (short) (-mystep); break; default: xdelta = 0; ydelta = 0; break; } return !screenp->query_passable((short) (controlx + xdelta), (short) (controly + ydelta), controller); } short statistics::right_walk() { short xdelta, ydelta; // if (walkrounds > 60) // if (direct_walk()) return -1; // walkrounds++; if (right_blocked() || right_forward_blocked() ) { if (!forward_blocked()) // walk forward { xdelta = controller->lastx; ydelta = controller->lasty; if (abs(xdelta) > abs(3*ydelta)) ydelta = 0; if (abs(ydelta) > abs(3*xdelta)) xdelta = 0; if (xdelta) xdelta /= abs(xdelta); if (ydelta) ydelta /= abs(ydelta); // return controller->walk(); return controller->walkstep(xdelta, ydelta); } else // turn left { controller->enddir = (char) ((controller->enddir+6) %8); // turn left return controller->turn(controller->enddir); } } else if (forward_blocked()) { controller->enddir = (char) ((controller->enddir+6) %8); // turn left return controller->turn(controller->enddir); } else if (right_back_blocked()) { controller->enddir = (char) ((controller->enddir+2) %8); // turn right switch (controller->enddir) { case FACE_UP: xdelta = 0; ydelta = -1; break; case FACE_UP_RIGHT: xdelta = 1; ydelta = -1; break; case FACE_RIGHT: xdelta = 1; ydelta = 0; break; case FACE_DOWN_RIGHT: xdelta = 1; ydelta = 1; break; case FACE_DOWN: xdelta = 0; ydelta = 1; break; case FACE_DOWN_LEFT: xdelta = -1; ydelta = 1; break; case FACE_LEFT: xdelta = -1; ydelta = 0; break; case FACE_UP_LEFT: xdelta = -1; ydelta = -1; break; default: xdelta = 0; ydelta = 0; break; } add_command(COMMAND_WALK, 1, xdelta, ydelta); } else { if (!direct_walk()) //we can't even walk straight to our foe { switch (controller->curdir) { case FACE_UP: xdelta = 0; ydelta = -1; break; case FACE_UP_RIGHT: xdelta = 1; ydelta = -1; break; case FACE_RIGHT: xdelta = 1; ydelta = 0; break; case FACE_DOWN_RIGHT: xdelta = 1; ydelta = 1; break; case FACE_DOWN: xdelta = 0; ydelta = 1; break; case FACE_DOWN_LEFT: xdelta = -1; ydelta = 1; break; case FACE_LEFT: xdelta = -1; ydelta = 0; break; case FACE_UP_LEFT: xdelta = -1; ydelta = -1; break; default: xdelta = 0; ydelta = 0; break; } //if (controller->spaces_clear() > 6) return controller->walkstep(xdelta, ydelta); } } return 1; } short statistics::direct_walk() { walker * foe = controller->foe; short xdest, ydest; short xdelta, ydelta; short xdeltastep, ydeltastep; short controlx = controller->xpos, controly = controller->ypos; // short xdistance, ydistance; // unsigned long tempdistance; // char olddir = controller->curdir; // short oldlastx = controller->lastx; // short oldlasty = controller->lasty; if (!foe) return 0; xdest = foe->xpos; ydest = foe->ypos; xdelta = (short) (xdest - controller->xpos); ydelta = (short) (ydest - controller->ypos); if (abs(xdelta) > abs(3*ydelta)) ydelta = 0; if (abs(ydelta) > abs(3*xdelta)) xdelta = 0; if (controller->fire_check(xdelta,ydelta)) { clear_command(); controller->turn(controller->facing(xdelta, ydelta)); add_command(COMMAND_ATTACK,(short) (30+random(25)),0,0); return 1; } if (xdelta) xdelta = (short) (xdelta / abs(xdelta)); if (ydelta) ydelta = (short) (ydelta / abs(ydelta)); xdeltastep = (short) (xdelta*controller->stepsize); ydeltastep = (short) (ydelta*controller->stepsize); // Tom's note on 8/3/97: I think these would work better if // replaced by some sort of single "if forward_blocked()" // check, otherwise I'm not sure if this works regardless of // current facing ... if (!controller->screenp->query_grid_passable(controlx+xdeltastep, controly+ydeltastep, controller) ) { if (!controller->screenp->query_grid_passable(controlx+xdeltastep,controly+0,controller) ) { if (!controller->screenp->query_grid_passable(controlx+0,controly+ydeltastep,controller) ) { walkrounds = 0; return 0; //we cannot get there by ANY of the straight line moves which //take us directy toward out foe } else //y ok { if (!ydelta) { walkrounds = 0; return 0; } controller->walkstep(0,ydelta); return 1; //walk in the y direction } } //end if(xd,0) else //x ok { if (!xdelta) { walkrounds = 0; return 0; } controller->walkstep(xdelta,0); return 1; //walk in the x direction } } else //x and y ok { if (!xdelta && !ydelta) { walkrounds = 0; return 0; } controller->walkstep(xdelta, ydelta); return 1; } //walk in the x and y direction } short statistics::walk_to_foe() { walker * foe = controller->foe; short xdest, ydest; short xdelta,ydelta; unsigned long tempdistance; static unsigned short do_check; short howmany; oblink * foelist; if (!foe || !random(300) ) //random just to be sure this gets reset sometime { last_distance = current_distance = 15000L; return 0; } do_check++; // This makes us only check every few rounds, to save // processing time if (!(do_check % 3)) { xdest = foe->xpos; ydest = foe->ypos; xdelta = (short) (xdest - controller->xpos); ydelta = (short) (ydest - controller->ypos); tempdistance = (unsigned long) controller->distance_to_ob(foe); if (tempdistance < 200 || (tempdistance < last_distance) ) { foelist = controller->screenp->find_foes_in_range(controller->screenp->oblist, 200, &howmany, controller); if (howmany > 0) { clear_command(); controller->turn(controller->facing(xdelta, ydelta)); controller->stats->try_command(COMMAND_ATTACK,(short) (30+ random(25)), 1, 1); controller->screenp->find_near_foe(controller); if (!controller->foe && foelist->ob) { controller->foe = foelist->ob; last_distance = controller->distance_to_ob(foe); } controller->init_fire(); delete_list(foelist); return 1; } else // our foe has moved; we need a new one { // Zardus: PORT: needs to check for commandlist if (commandlist) commandlist->commandcount = 0; //clear_command(); } } } //end if do_check /* if (tempdistance <= last_distance)// are we closer than we've ever been? last_distance = tempdistance; // then set our checking distance .. if (!direct_walk()) // Can we walk in a direct line to foe? { right_walk(); // If not, use right-hand walking } */ if (tempdistance < last_distance)// are we closer than we've ever been? { last_distance = tempdistance; // then set our checking distance .. if (!direct_walk()) // Can we walk in a direct line to foe? { right_walk(); // If not, use right-hand walking } } else right_walk(); // Are we really really close? Stop searching, then :) // Zardus: lets check if commandlist exists, too if (tempdistance < 30 && commandlist) { commandlist->commandcount = 0; //clear_command(); } return 1; } // Stuff for command? command::command() { commandtype = 0; commandcount = 0; com1 = com2 = 0; next = NULL; }