#include <math.h>
#include "mech.h"
#include "autopilot.h"
#include "p.autopilot_command.h"
#include "p.mech.utils.h"
#include "p.map.obj.h"
#include "spath.h"
#include "p.mech.combat.h"
#include "p.glue.hcode.h"
Include dependency graph for autopilot_ai.c:
Go to the source code of this file.
Data Structures | |
struct | LOC |
Defines | |
#define | SCORE_MOD 100 |
#define | SAFE_SCORE SCORE_MOD * 1000 |
#define | MIN_SAFE 8 |
#define | NORM_SAFE 32 |
#define | MAX_SIM_PATHS 40 |
#define | MNORM_COUNT 37 |
#define | CFAST_COUNT 9 |
#define | Floodable(loc) (!GetSectArmor(m,loc) || (!GetSectRArmor(m,loc) && GetSectORArmor(m,loc))) |
#define | FloodCheck(loc) if (GetSectInt(m,loc)) if (Floodable(loc)) return 1; |
#define | MAGIC_NUM -123456 |
#define | U1(a, b) if (a < b || a == MAGIC_NUM) a = b |
#define | U2(a, b) if (a > b || a == MAGIC_NUM) a = b |
#define | FU(a, b, c, s) ((b) == (c) ? 0 : (s) * ((a) - (b)) / ((c) - (b))) |
#define | UNREF(a, b, mod) if (a != MAGIC_NUM && b != MAGIC_NUM) { int c = a, d = b; a = (c * (mod - 1) + d) / mod; b = (c + d * (mod - 1)) / mod; } |
Enumerations | |
enum | { SP_OPT_NORM, SP_OPT_FASTER, SP_OPT_SLOWER, SP_OPT_C } |
Functions | |
void | sendAIM (AUTO *a, MECH *m, char *msg) |
char * | AI_Info (MECH *m, AUTO *a) |
float | terrain_speed (MECH *mech, float tempspeed, float maxspeed, int terrain, int elev) |
static int | ai_crash (MAP *map, MECH *m, LOC *l) |
static void | LOCInit (LOC *l, MECH *m) |
int | getEnemies (MECH *mech, MAP *map, int reset) |
int | getFriends (MECH *mech, MAP *map, int reset) |
void | ai_path_score (MECH *m, MAP *map, AUTO *a, int opts[][2], int num_o, int gotenemy, float dx, float dy, float delx, float dely, int *rl, int *bd, int *bscore) |
int | ai_max_speed (MECH *m, AUTO *a) |
int | ai_opponents (AUTO *a, MECH *m) |
void | ai_run_speed (MECH *mech, AUTO *a) |
void | ai_stop (MECH *mech, AUTO *a) |
void | ai_set_speed (MECH *mech, AUTO *a, float spd) |
void | ai_set_heading (MECH *mech, AUTO *a, int dir) |
void | ai_adjust_move (AUTO *a, MECH *m, char *text, int hmod, int smod, int b_score) |
int | ai_check_path (MECH *m, AUTO *a, float dx, float dy, float delx, float dely) |
void | ai_init (AUTO *a, MECH *m) |
int | artillery_round_flight_time (float fx, float fy, float tx, float ty) |
static int | mech_snipe_func (MECH *mech, dbref player, int index, int high) |
void | mech_snipe (dbref player, MECH *mech, char *buffer) |
static astar_node * | auto_create_astar_node (short x, short y, short x_parent, short y_parent, short g_score, short h_score) |
int | astar_compare (int a, int b, void *arg) |
void | astar_release (void *key, void *data) |
int | auto_astar_generate_path (AUTO *autopilot, MECH *mech, short end_x, short end_y) |
void | astar_smooth_path (AUTO *autopilot) |
void | auto_destroy_astar_path (AUTO *autopilot) |
Variables | |
int | sp_opt [SP_OPT_C] = { 0, 1, -1 } |
int | move_norm_opt [MNORM_COUNT][2] |
int | combat_fast_opt [CFAST_COUNT][2] |
static LOC | enemy_l [MAX_MECHS_PER_MAP] |
static MECH * | enemy_m [MAX_MECHS_PER_MAP] |
static int | enemy_o [MAX_MECHS_PER_MAP] |
static int | enemy_i [MAX_MECHS_PER_MAP] |
static int | enemy_c = 0 |
static LOC | friend_l [MAX_MECHS_PER_MAP] |
static MECH * | friend_m [MAX_MECHS_PER_MAP] |
static int | friend_o [MAX_MECHS_PER_MAP] |
static int | friend_i [MAX_MECHS_PER_MAP] |
static int | friend_c = 0 |
static MECH * | target_mech |
#define CFAST_COUNT 9 |
#define Floodable | ( | loc | ) | (!GetSectArmor(m,loc) || (!GetSectRArmor(m,loc) && GetSectORArmor(m,loc))) |
Referenced by ai_crash().
Definition at line 406 of file autopilot_ai.c.
#define MAGIC_NUM -123456 |
#define MAX_SIM_PATHS 40 |
#define MIN_SAFE 8 |
#define MNORM_COUNT 37 |
#define NORM_SAFE 32 |
#define SAFE_SCORE SCORE_MOD * 1000 |
#define SCORE_MOD 100 |
Definition at line 32 of file autopilot_ai.c.
#define U1 | ( | a, | |||
b | ) | if (a < b || a == MAGIC_NUM) a = b |
Definition at line 404 of file autopilot_ai.c.
#define U2 | ( | a, | |||
b | ) | if (a > b || a == MAGIC_NUM) a = b |
Definition at line 405 of file autopilot_ai.c.
anonymous enum |
Definition at line 47 of file autopilot_ai.c.
00047 { 00048 SP_OPT_NORM, SP_OPT_FASTER, SP_OPT_SLOWER, SP_OPT_C 00049 };
Definition at line 785 of file autopilot_ai.c.
References AI_Info(), ai_set_heading(), ai_set_speed(), MechDesiredFacing, MechDesiredSpeed, MMaxSpeed, MP1, SendAI, SP_OPT_FASTER, and SP_OPT_SLOWER.
Referenced by ai_check_path().
00787 { 00788 float ms; 00789 00790 ai_set_heading(m, a, MechDesiredFacing(m) + hmod); 00791 switch (smod) { 00792 default: 00793 SendAI("%s state: %s (hmod:%d) sc:%d", AI_Info(m, a), text, hmod, 00794 b_score); 00795 break; 00796 case SP_OPT_FASTER: 00797 SendAI("%s state: %s+accelerating (hmod:%d) sc:%d", AI_Info(m, a), 00798 text, hmod, b_score); 00799 ms = MMaxSpeed(m); 00800 ai_set_speed(m, a, 00801 (float) ((MechDesiredSpeed(m) < 00802 MP1 ? MP1 : MechDesiredSpeed(m)) * 4.0 / 3.0)); 00803 break; 00804 case SP_OPT_SLOWER: 00805 SendAI("%s state: %s+decelerating (hmod:%d) sc:%d", AI_Info(m, a), 00806 text, hmod, b_score); 00807 ms = MMaxSpeed(m); 00808 ai_set_speed(m, a, (int) (MechDesiredSpeed(m) * 2.0 / 3.0)); 00809 break; 00810 } 00811 }
Definition at line 813 of file autopilot_ai.c.
References ai_adjust_move(), AI_Info(), ai_opponents(), ai_path_score(), ai_stop(), AUTO_GOET, AUTO_GOTT, AUTOPILOT_GOTO_TICK, AUTO::b_bsc, AUTO::b_dan, AUTO::b_msc, CFAST_COUNT, CLASS_MECH, combat_fast_opt, getEnemies(), getFriends(), getMap(), AUTO::last_upd, MAGIC_NUM, MECH::mapindex, MAX, MechType, MIN_SAFE, MNORM_COUNT, move_norm_opt, mudstate, muxevent_tick, statedata::now, SAFE_SCORE, SendAI, sendAIM(), UNREF, AUTO::w_bsc, AUTO::w_dan, and AUTO::w_msc.
Referenced by auto_goto_event().
00815 { 00816 int o; 00817 int b_len, bl, b, b_score; 00818 MAP *map = getMap(m->mapindex); 00819 00820 o = ai_opponents(a, m); 00821 if(a->last_upd > mudstate.now || (mudstate.now - a->last_upd) > AUTO_GOET) { 00822 if((muxevent_tick - a->last_upd) > AUTO_GOTT) { 00823 a->b_msc = MAGIC_NUM; 00824 a->w_msc = MAGIC_NUM; 00825 a->b_bsc = MAGIC_NUM; 00826 a->w_bsc = MAGIC_NUM; 00827 a->b_dan = MAGIC_NUM; 00828 a->b_dan = (40 + 20 * 29 + 100) * 30; /* To stay focused */ 00829 } else { 00830 /* Slight update ; Un-refine the goals somewhat */ 00831 UNREF(a->w_msc, a->b_msc, 3); 00832 UNREF(a->w_bsc, a->b_bsc, 5); 00833 UNREF(a->w_dan, a->b_dan, 8); 00834 a->b_dan = MAX(a->b_dan, (40 + 20 * 29 + 100) * 30); /* To stay focused */ 00835 } 00836 a->last_upd = mudstate.now; 00837 } 00838 /* Got either opponents (nasty) or [possibly] blocked path (slightly nasty), i.e. 12sec */ 00839 if(MechType(m) == CLASS_MECH) 00840 getFriends(m, map, 0); 00841 if(o) { 00842 getEnemies(m, map, 0); 00843 if(!((muxevent_tick / AUTOPILOT_GOTO_TICK) % 4)) { /* Just every fourth tick, i.e. 12sec */ 00844 /* Thorough check */ 00845 ai_path_score(m, map, a, move_norm_opt, MNORM_COUNT, 1, dx, dy, 00846 delx, dely, &bl, &b, &b_score); 00847 b_len = b_score / SAFE_SCORE; 00848 if(b_len >= MIN_SAFE) 00849 ai_adjust_move(a, m, "combat(/twitchy)", 00850 move_norm_opt[b][0], move_norm_opt[b][1], 00851 b_score); 00852 } else { 00853 ai_path_score(m, map, a, combat_fast_opt, CFAST_COUNT, 1, dx, 00854 dy, delx, dely, &bl, &b, &b_score); 00855 b_len = b_score / SAFE_SCORE; 00856 if(b_len >= MIN_SAFE) 00857 ai_adjust_move(a, m, "[f]combat(/twitchy)", 00858 combat_fast_opt[b][0], combat_fast_opt[b][1], 00859 b_score); 00860 } 00861 return 1; /* We want to keep fighting near foes */ 00862 } 00863 if(!((muxevent_tick / AUTOPILOT_GOTO_TICK) % 4)) { /* Just every fourth tick, i.e. 12sec */ 00864 /* Thorough check */ 00865 ai_path_score(m, map, a, move_norm_opt, MNORM_COUNT, 0, dx, dy, 00866 delx, dely, &bl, &b, &b_score); 00867 b_len = b_score / SAFE_SCORE; 00868 if(b_len >= MIN_SAFE) 00869 ai_adjust_move(a, m, "moving", move_norm_opt[b][0], 00870 move_norm_opt[b][1], b_score); 00871 } else { 00872 ai_path_score(m, map, a, combat_fast_opt, CFAST_COUNT, 0, dx, dy, 00873 delx, dely, &bl, &b, &b_score); 00874 b_len = b_score / SAFE_SCORE; 00875 if(b_len >= MIN_SAFE) 00876 ai_adjust_move(a, m, "[f]moving", combat_fast_opt[b][0], 00877 combat_fast_opt[b][1], b_score); 00878 } 00879 00880 if(b_len >= MIN_SAFE) 00881 return 1; 00882 00883 /* Slow down + stop - no sense in dying needlessly */ 00884 ai_stop(m, a); 00885 SendAI("%s state: panic", AI_Info(m, a)); 00886 sendAIM(a, m, "PANIC! Unable to comply with order."); 00887 return 0; 00888 }
Definition at line 126 of file autopilot_ai.c.
References ACCEL_MOD, BOUNDED(), confdata::btech_slowdown, CLASS_BSUIT, CLASS_MECH, CLASS_MW, CLASS_VEH_GROUND, LOC::dh, LOC::ds, LOC::e, Elevation, FindComponents(), FloodCheck, LOC::fx, LOC::fy, GetRTerrain, GYRO_DESTROYED, LOC::h, HEAVY_FOREST, HIGHWATER, is_aero, IsDS, Landed, LARM, LLEG, LOC::lx, LOC::ly, MAP::map_height, MAP::map_width, MAX, MechCritStatus, MechDesiredFacing, MechFacing, MechIsQuad, MechLateral, MechMove, MechType, MMaxSpeed, MOVE_FLY, MOVE_HOVER, MOVE_MOD, MOVE_TRACK, MOVE_VTOL, MOVE_WHEEL, MP1, MP_PER_KPH, mudconf, NUM_SECTIONS, RARM, RealCoordToMapCoord(), RLEG, LOC::s, LOC::t, terrain_speed(), WATER, LOC::x, and LOC::y.
Referenced by ai_path_score(), and mech_snipe_func().
00127 { 00128 float newx = 0.0, newy = 0.0; 00129 float tempspeed, maxspeed, acc; 00130 int offset; 00131 int normangle; 00132 int mw_mod = 1; 00133 int ch = 0; 00134 00135 if(!map) 00136 return 0; 00137 00138 maxspeed = MMaxSpeed(m); 00139 00140 /* UpdateHeading */ 00141 if(l->h != l->dh && !(MechCritStatus(m) & GYRO_DESTROYED)) { 00142 ch = 1; 00143 if(is_aero(m)) 00144 maxspeed = maxspeed * ACCEL_MOD; 00145 normangle = l->h - l->dh; 00146 if(MechType(m) == CLASS_MW || MechType(m) == CLASS_BSUIT) 00147 mw_mod = 60; 00148 /* XXX Jumping */ 00149 if(fabs(l->s) < 1.0) 00150 offset = 3 * maxspeed * MP_PER_KPH * mw_mod; 00151 else { 00152 offset = 2 * maxspeed * MP_PER_KPH * mw_mod; 00153 if((abs(normangle) > offset) && (l->s > (maxspeed * 2 / 3))) 00154 offset -= offset / 2 * (3.0 * l->s / maxspeed - 2.0); 00155 } 00156 offset = offset * MOVE_MOD; 00157 if(normangle < 0) 00158 normangle += 360; 00159 if(IsDS(m) && offset >= 10) 00160 offset = 10; 00161 if(normangle > 180) { 00162 l->h += offset; 00163 if(l->h >= 360) 00164 l->h -= 360; 00165 normangle += offset; 00166 if(normangle >= 360) 00167 l->h = l->dh; 00168 } else { 00169 l->h -= offset; 00170 if(l->h < 0) 00171 l->h += 360; 00172 normangle -= offset; 00173 if(normangle < 0) 00174 l->h = l->dh; 00175 } 00176 00177 } 00178 /* UpdateSpeed */ 00179 /* XXX MASC */ 00180 /* XXX heat (_hard_ to track) */ 00181 tempspeed = l->ds; 00182 if(MechType(m) != CLASS_MW && MechMove(m) != MOVE_VTOL && 00183 (MechMove(m) != MOVE_FLY || Landed(m))) 00184 tempspeed = terrain_speed(m, tempspeed, maxspeed, l->t, l->e); 00185 if(ch) { 00186 if(mudconf.btech_slowdown == 2) { 00187 int dif = MechFacing(m) - MechDesiredFacing(m); 00188 00189 if(dif < 0) 00190 dif = -dif; 00191 if(dif > 180) 00192 dif = 360 - dif; 00193 if(dif) { 00194 dif = (dif - 1) / 30 + 2; 00195 tempspeed = tempspeed * (10 - dif) / 10; 00196 } 00197 } else if(mudconf.btech_slowdown == 1) { 00198 if(l->h != l->dh) 00199 tempspeed = tempspeed * 2.0 / 3.0; 00200 else 00201 tempspeed = tempspeed * 3.0 / 4.0; 00202 } 00203 } 00204 if(MechIsQuad(m) && MechLateral(m)) 00205 tempspeed -= MP1; 00206 if(tempspeed <= 0.0) { 00207 tempspeed = 0.0; 00208 } 00209 if(l->ds < 0.) 00210 tempspeed = -tempspeed; 00211 if(tempspeed != l->s) { 00212 if(MechIsQuad(m)) 00213 acc = maxspeed / 10.; 00214 else 00215 acc = maxspeed / 20.; 00216 if(tempspeed < l->s) { 00217 /* Decelerating */ 00218 l->s -= acc; 00219 if(tempspeed > l->s) 00220 l->s = tempspeed; 00221 } else { 00222 /* Accelerating */ 00223 l->s += acc; 00224 if(tempspeed < l->s) 00225 l->s = tempspeed; 00226 } 00227 } 00228 /* move_mech + NewHexEntered */ 00229 /* XXX Jumping mechs [aeros,VTOLs] */ 00230 /* XXX Non-mechs */ 00231 /* XXX Quads */ 00232 FindComponents(l->s * MOVE_MOD, l->h, &newx, &newy); 00233 l->fx += newx; 00234 l->fy += newy; 00235 l->lx = l->x; 00236 l->ly = l->y; 00237 RealCoordToMapCoord(&l->x, &l->y, l->fx, l->fy); 00238 /* Ensure we don't run off map */ 00239 if(BOUNDED(0, l->x, map->map_width - 1) != l->x) 00240 return 1; 00241 if(BOUNDED(0, l->y, map->map_height - 1) != l->y) 00242 return 1; 00243 if(l->lx != l->x || l->ly != l->y) { 00244 int oz = l->e; 00245 00246 /* Ensure if mech m can do transition auto_lx,auto_ly => auto_x,auto_y */ 00247 00248 /* XXX Decent handling of terrain choosing and stuff */ 00249 switch (GetRTerrain(map, l->x, l->y)) { 00250 case HEAVY_FOREST: 00251 if(MechType(m) != CLASS_MECH) 00252 return 1; 00253 break; 00254 case WATER: 00255 if(MechMove(m) == MOVE_TRACK || MechMove(m) == MOVE_WHEEL) 00256 return 1; 00257 else { 00258 /* Check floodability for mechs */ 00259 if(MechType(m) == CLASS_MECH) { 00260 int t = Elevation(map, l->x, l->y); 00261 00262 if(t < 0) { 00263 if(t == -1) { 00264 /* Check feet */ 00265 #define Floodable(loc) (!GetSectArmor(m,loc) || (!GetSectRArmor(m,loc) && GetSectORArmor(m,loc))) 00266 #define FloodCheck(loc) if (GetSectInt(m,loc)) if (Floodable(loc)) return 1; 00267 FloodCheck(LLEG); 00268 FloodCheck(RLEG); 00269 if(MechIsQuad(m)) { 00270 FloodCheck(LARM); 00271 FloodCheck(RARM); 00272 } 00273 } else { 00274 int i; 00275 00276 for(i = 0; i < NUM_SECTIONS; i++) 00277 FloodCheck(i); 00278 } 00279 } 00280 } 00281 } 00282 break; 00283 case HIGHWATER: 00284 return 1; 00285 break; 00286 } 00287 l->e = Elevation(map, l->x, l->y); 00288 if(MechMove(m) == MOVE_HOVER) 00289 l->e = MAX(0, l->e); 00290 l->t = GetRTerrain(map, l->x, l->y); 00291 if(MechType(m) == CLASS_MECH) 00292 if((l->e - oz) > 2 || (oz - l->e) > 2) 00293 return 1; 00294 /* XXX Check flooding etc, should avoid _that_ */ 00295 if(MechType(m) == CLASS_VEH_GROUND) 00296 if((l->e - oz) > 1 || (oz - l->e) > 1) 00297 return 1; 00298 00299 } 00300 return 0; 00301 }
Definition at line 115 of file autopilot_ai.c.
References MECH::mapindex, MBUF_SIZE, MECH::mynum, and AUTO::mynum.
Referenced by ai_adjust_move(), and ai_check_path().
00116 { 00117 static char buf[MBUF_SIZE]; 00118 00119 sprintf(buf, "Unit#%d on #%d [A#%d]:", m->mynum, m->mapindex, a->mynum); 00120 return buf; 00121 }
Definition at line 890 of file autopilot_ai.c.
References AUTO::auto_cdist, AUTO::auto_cmode, AUTO::auto_fweight, AUTO::auto_goweight, AUTO::auto_nervous, AUTO::flags, AUTO::speed, and AUTO::target.
00891 { 00892 00893 /* XXX Analyze our unit type ; set basic combat tactic */ 00894 a->auto_cmode = 1; /* CHARGE! */ 00895 a->auto_cdist = 2; /* Attempt to avoid kicking distance */ 00896 a->auto_nervous = 0; 00897 a->auto_goweight = 44; /* We're mainly concentrating on fighting */ 00898 a->auto_fweight = 55; 00899 a->speed = 100; /* Reset to full speed */ 00900 a->flags = 0; 00901 a->target = -1; 00902 }
Definition at line 692 of file autopilot_ai.c.
References MechDesiredSpeed, and MMaxSpeed.
Referenced by ai_run_speed().
00693 { 00694 float ms; 00695 00696 if(MechDesiredSpeed(m) != (ms = MMaxSpeed(m))) 00697 return 0; 00698 return 1; 00699 }
Definition at line 701 of file autopilot_ai.c.
References AUTO::auto_nervous, and MechNumSeen.
Referenced by ai_check_path().
00702 { 00703 if(a->auto_nervous) { 00704 a->auto_nervous--; 00705 return 1; 00706 } 00707 if(MechNumSeen(m)) 00708 a->auto_nervous = 30; /* We'll stay frisky for awhile even if cons are lost for one reason or another */ 00709 return MechNumSeen(m); 00710 }
void ai_path_score | ( | MECH * | m, | |
MAP * | map, | |||
AUTO * | a, | |||
int | opts[][2], | |||
int | num_o, | |||
int | gotenemy, | |||
float | dx, | |||
float | dy, | |||
float | delx, | |||
float | dely, | |||
int * | rl, | |||
int * | bd, | |||
int * | bscore | |||
) |
Definition at line 408 of file autopilot_ai.c.
References AcceptableDegree(), ai_crash(), AUTO::auto_cdist, AUTO::auto_cmode, BOUNDED(), BSIDE, CLASS_MECH, CLASS_VEH_GROUND, LOC::dh, LOC::ds, enemy_c, enemy_l, enemy_m, enemy_o, FindBearing(), FindXYRange(), friend_c, friend_l, friend_m, friend_o, FSIDE, GetSectArmor, GetSectOArmor, LOC::h, LOCInit(), LSIDE, MAX, MAX_SIM_PATHS, MechType, MIN, MMaxSpeed, MP1, MP2, MP4, MP6, MP9, MyHexDist(), NORM_SAFE, RSIDE, sp_opt, SP_OPT_FASTER, WATER, x, and y.
Referenced by ai_check_path().
00411 { 00412 int i, j, k, l, bearing; 00413 int sd, sc; 00414 LOC lo[MAX_SIM_PATHS]; 00415 int dan[MAX_SIM_PATHS], tdan[MAX_SIM_PATHS], msc[MAX_SIM_PATHS], 00416 bsc[MAX_SIM_PATHS]; 00417 int out[MAX_SIM_PATHS], stack[MAX_SIM_PATHS], br[MAX_SIM_PATHS]; 00418 00419 for(i = 0; i < num_o; i++) { 00420 msc[i] = 0; 00421 bsc[i] = 0; 00422 dan[i] = 0; 00423 tdan[i] = 0; 00424 out[i] = 0; 00425 stack[i] = 0; 00426 br[i] = 9999; 00427 LOCInit(&lo[i], m); 00428 lo[i].dh = AcceptableDegree(lo[i].dh + opts[i][0]); 00429 sd = sp_opt[opts[i][1]]; 00430 if(sd) { 00431 if(sd < 0) { 00432 lo[i].ds = lo[i].ds * 2.0 / 3.0; 00433 } else if(sd == 1) { 00434 float ms = MMaxSpeed(m); 00435 00436 lo[i].ds = (lo[i].ds < MP1 ? MP1 : lo[i].ds) * 4.0 / 3.0; 00437 if(lo[i].ds > ms) 00438 lo[i].ds = ms; 00439 } else { 00440 float ms = MMaxSpeed(m); 00441 00442 lo[i].ds = ms; 00443 } 00444 } 00445 } 00446 for(i = 0; i < NORM_SAFE; i++) { 00447 dx += delx; 00448 dy += dely; 00449 for(k = 0; k < num_o; k++) { 00450 if(out[k]) 00451 continue; 00452 if(ai_crash(map, m, &lo[k])) { /* Simulate _one_ step */ 00453 out[k] = i + 1; 00454 continue; 00455 } 00456 /* Base target-acquisition stuff */ 00457 if((l = FindXYRange(lo[k].fx, lo[k].fy, dx, dy)) < br[k]) 00458 br[k] = l; 00459 00460 /* Generally speaking we're going to the point spesified */ 00461 msc[k] += 4 * (2 * (50 - br[k]) + (100 - l)); 00462 00463 /* Heading change's inherently [slightly] evil */ 00464 if(lo[k].h != lo[k].dh) 00465 msc[k] -= 1; 00466 00467 /* Moving is a good thing */ 00468 if(lo[k].x != lo[k].lx || lo[k].y != lo[k].ly) { 00469 if(lo[k].t == WATER) 00470 msc[k] -= 5; 00471 msc[k] += 10; 00472 } 00473 /* Punish for not utilizing full speed (this is .. hm, flaky) */ 00474 if(opts[k][1] != SP_OPT_FASTER && MMaxSpeed(m) > 0.1) { 00475 sc = BOUNDED(0, 100 * lo[k].ds / MMaxSpeed(m), 100); 00476 msc[k] -= (100 - sc) / 30; /* Basically, unused speed is bad */ 00477 } 00478 } 00479 if(MechType(m) == CLASS_MECH) { 00480 /* Simulate friends */ 00481 for(j = 0; j < friend_c; j++) { 00482 if(friend_o[j]) 00483 continue; 00484 if(ai_crash(map, friend_m[j], &friend_l[j])) 00485 friend_o[j] = 1; 00486 } 00487 for(k = 0; k < num_o; k++) { 00488 int sc = 0; 00489 00490 if(out[k] || stack[k]) 00491 continue; 00492 /* Meaning of stack: Someone moves _into_ the hex */ 00493 for(j = 0; j < friend_c; j++) 00494 if(!friend_o[j]) 00495 if(lo[k].x == friend_l[j].x && 00496 lo[k].y == friend_l[j].y) 00497 sc++; 00498 if(sc > 1) { /* Possible stackage */ 00499 int osc = sc; 00500 00501 for(j = 0; j < friend_c; j++) 00502 if(!friend_o[j]) 00503 if(lo[k].x == friend_l[j].x && 00504 lo[k].y == friend_l[j].y) 00505 if((lo[k].lx != lo[k].x || 00506 lo[k].ly != lo[k].y) || 00507 (friend_l[j].lx != friend_l[j].x || 00508 friend_l[j].ly != friend_l[j].y)) 00509 osc--; 00510 if(osc != sc) 00511 stack[k] = i + 1; 00512 } 00513 if(gotenemy) 00514 tdan[k] = 0; 00515 } 00516 } 00517 if(gotenemy) { 00518 /* Update enemy locations as well */ 00519 for(j = 0; j < enemy_c; j++) { 00520 if(enemy_o[j]) 00521 continue; 00522 if(ai_crash(map, enemy_m[j], &enemy_l[j])) 00523 enemy_o[j] = 1; 00524 for(k = 0; k < num_o; k++) { 00525 if(out[k]) 00526 continue; 00527 if((l = MyHexDist(lo[k].x, lo[k].y, enemy_l[j].x, 00528 enemy_l[j].y, 0)) >= 100) 00529 continue; 00530 switch (a->auto_cmode) { 00531 case 0: /* Withdraw */ 00532 if(l > a->auto_cdist) 00533 bsc[k] += 5 * a->auto_cdist + l - a->auto_cdist; 00534 else 00535 bsc[k] += 5 * l; 00536 break; 00537 case 1: /* Score = fulfilling goal (=> distance from cdist) */ 00538 if(l < a->auto_cdist) 00539 bsc[k] -= 10 * (a->auto_cdist - l); /* Not too close */ 00540 else 00541 bsc[k] -= 2 * (l - a->auto_cdist); 00542 break; 00543 case 2: 00544 if(l < a->auto_cdist) 00545 bsc[k] -= 2 * (a->auto_cdist - l); 00546 else 00547 bsc[k] -= 10 * (l - a->auto_cdist); 00548 } 00549 if(l > 28) 00550 continue; 00551 /* Danger modifier ; it's _always_ dangerous to be close */ 00552 tdan[k] += (40 - MIN(40, l)); 00553 /* Arcs can be .. dangerous */ 00554 if(MechType(m) == CLASS_MECH) { 00555 bearing = 00556 FindBearing(lo[k].fx, lo[k].fy, enemy_l[j].fx, 00557 enemy_l[j].fy); 00558 bearing = lo[k].h - bearing; 00559 if(bearing < 0) 00560 bearing += 360; 00561 if(bearing >= 90 && bearing <= 270) { 00562 /* Sides are moderately dangerous [potential rear arcs] */ 00563 tdan[k] += 5 * (29 - MIN(29, l)); 00564 if(bearing >= 120 && bearing <= 240) { 00565 /* Rear arc is VERY dangerous */ 00566 tdan[k] += 20 * (29 - MIN(29, l)); 00567 } 00568 } 00569 } else if(MechType(m) == CLASS_VEH_GROUND) { 00570 bearing = 00571 FindBearing(lo[k].fx, lo[k].fy, enemy_l[j].fx, 00572 enemy_l[j].fy); 00573 bearing = lo[k].h - bearing; 00574 if(bearing < 0) 00575 bearing += 360; 00576 if(bearing >= 45 && bearing <= 315) { 00577 if(bearing >= 135 && bearing <= 225) { 00578 /* Rear arc is VERY dangerous */ 00579 tdan[k] += 00580 10 * (29 - MIN(29, 00581 l)) * (100 - 00582 100 * 00583 GetSectArmor(m, 00584 BSIDE) 00585 / MAX(1, 00586 GetSectOArmor 00587 (m, 00588 BSIDE))) / 00589 100; 00590 } else if(bearing < 135) { 00591 /* right side */ 00592 tdan[k] += 00593 7 * (29 - MIN(29, 00594 l)) * (100 - 00595 100 * GetSectArmor(m, 00596 RSIDE) 00597 / MAX(1, 00598 GetSectOArmor 00599 (m, 00600 RSIDE))) / 00601 100; 00602 } else { 00603 tdan[k] += 00604 7 * (29 - MIN(29, 00605 l)) * (100 - 00606 100 * GetSectArmor(m, 00607 LSIDE) 00608 / MAX(1, 00609 GetSectOArmor 00610 (m, 00611 LSIDE))) / 00612 100; 00613 } 00614 } else 00615 tdan[k] += 00616 5 * (29 - MIN(29, 00617 l)) * (100 - 00618 100 * GetSectArmor(m, 00619 FSIDE) 00620 / MAX(1, 00621 GetSectOArmor(m, 00622 FSIDE))) 00623 / 100; 00624 } 00625 } 00626 for(k = 0; k < num_o; k++) { 00627 if(out[k]) 00628 continue; 00629 /* Dangerous to be far from buddy in fight */ 00630 l = FindXYRange(lo[k].fx, lo[k].fy, dx, dy); 00631 if(gotenemy && (delx != 0.0 || dely != 0.0)) 00632 tdan[k] += MIN(100, l * l); 00633 if(enemy_c) 00634 tdan[k] = tdan[k] / enemy_c; 00635 /* It's inherently dangerous to move slowly: */ 00636 if(lo[k].s <= MP2) 00637 tdan[k] += 400; 00638 else if(lo[k].s <= MP4) 00639 tdan[k] += 300; 00640 else if(lo[k].s <= MP6) 00641 tdan[k] += 200; 00642 else if(lo[k].s <= MP9) 00643 tdan[k] += 100; 00644 dan[k] += tdan[k] * (NORM_SAFE - i) / (NORM_SAFE / 2); 00645 } 00646 } 00647 } 00648 } 00649 for(i = 0; i < num_o; i++) { 00650 U2(a->w_msc, msc[i]); 00651 U1(a->b_msc, msc[i]); 00652 if(gotenemy) { 00653 U2(a->w_bsc, bsc[i]); 00654 U1(a->b_bsc, bsc[i]); 00655 U2(a->w_dan, dan[i]); 00656 U1(a->b_dan, dan[i]); 00657 } 00658 } 00659 /* Now we have been.. calibrated */ 00660 *bscore = 0; 00661 *bd = -1; 00662 /* Find best overall score */ 00663 for(i = 0; i < num_o; i++) { 00664 if(!out[i]) 00665 out[i] = NORM_SAFE + 1; 00666 if(!stack[i]) 00667 stack[i] = out[i]; 00668 sc = (out[i] - (out[i] - stack[i]) / 2) * SAFE_SCORE + FU(msc[i], 00669 a->w_msc, 00670 a->b_msc, 00671 SCORE_MOD * 00672 a-> 00673 auto_goweight); 00674 if(gotenemy) 00675 sc += 00676 FU(bsc[i], a->w_bsc, a->b_bsc, 00677 SCORE_MOD * a->auto_fweight) - FU(dan[i], a->w_dan, 00678 a->b_dan, 00679 SCORE_MOD * 00680 (a->auto_fweight + 00681 a->auto_goweight)); 00682 if(sc > *bscore 00683 || (*bd >= 0 && sc == *bscore 00684 && sp_opt[opts[i][1]] > sp_opt[opts[*bd][1]])) { 00685 *bscore = sc; 00686 *bd = i; 00687 *rl = out[i] - 1; 00688 } 00689 } 00690 }
Definition at line 712 of file autopilot_ai.c.
References ai_max_speed(), mech_speed(), and AUTO::mynum.
00713 { 00714 /* Warp speed, cap'n! */ 00715 char buf[128]; 00716 00717 if(!ai_max_speed(mech, a)) { 00718 strcpy(buf, "run"); 00719 mech_speed(a->mynum, mech, buf); 00720 } 00721 }
Definition at line 773 of file autopilot_ai.c.
References mech_heading(), MechDesiredFacing, and AUTO::mynum.
Referenced by ai_adjust_move().
00774 { 00775 char buf[128]; 00776 00777 if(dir == MechDesiredFacing(mech)) 00778 return; 00779 sprintf(buf, "%d", dir); 00780 mech_heading(a->mynum, mech, buf); 00781 }
Definition at line 757 of file autopilot_ai.c.
References FBOUNDED(), mech_speed(), MechDesiredSpeed, MMaxSpeed, AUTO::mynum, SBUF_SIZE, and AUTO::speed.
Referenced by ai_adjust_move(), auto_astar_follow_event(), auto_astar_goto_event(), auto_astar_roam_event(), auto_dumbgoto_event(), auto_enter_event(), auto_goto_event(), auto_leave_event(), slow_down_if_neccessary(), and speed_up_if_neccessary().
00758 { 00759 char buf[SBUF_SIZE]; 00760 float newspeed; 00761 00762 if(!mech || !a) 00763 return; 00764 00765 newspeed = FBOUNDED(0, spd, ((MMaxSpeed(mech) * a->speed) / 100.0)); 00766 00767 if(MechDesiredSpeed(mech) != newspeed) { 00768 sprintf(buf, "%f", newspeed); 00769 mech_speed(a->mynum, mech, buf); 00770 } 00771 }
Definition at line 723 of file autopilot_ai.c.
References mech_speed(), MechDesiredSpeed, and AUTO::mynum.
Referenced by ai_check_path().
00724 { 00725 char buf[128]; 00726 00727 if(MechDesiredSpeed(mech) > 0.1) { 00728 strcpy(buf, "stop"); 00729 mech_speed(a->mynum, mech, buf); 00730 } 00731 }
int artillery_round_flight_time | ( | float | fx, | |
float | fy, | |||
float | tx, | |||
float | ty | |||
) |
Definition at line 81 of file artillery.c.
00082 { 00083 int delay = MAX(ARTILLERY_MINIMUM_FLIGHT, 00084 (FindHexRange(fx, fy, tx, ty) / ARTY_SPEED)); 00085 00086 /* XXX Different weapons, diff. speed? */ 00087 return delay; 00088 }
int astar_compare | ( | int | a, | |
int | b, | |||
void * | arg | |||
) |
void astar_release | ( | void * | key, | |
void * | data | |||
) |
void astar_smooth_path | ( | AUTO * | autopilot | ) |
Definition at line 1506 of file autopilot_ai.c.
01507 { 01508 01509 dllist_node *current, *next, *prev; 01510 01511 float x1, y1, x2, y2; 01512 int degrees; 01513 01514 /* Get the n node off the list */ 01515 01516 /* Get the n+1 node off the list */ 01517 01518 /* Get bearing from n to n+1 */ 01519 01520 /* Get n+2 node off list */ 01521 01522 /* Get bearing from n to n+2 node */ 01523 01524 /* Compare bearings */ 01525 /* If in same direction as previous 01526 * don't need n+1 node */ 01527 01528 /* Keep looping till bearing doesn't match */ 01529 /* Then reset n node to final node and continue */ 01530 01531 return; 01532 01533 }
Definition at line 994 of file autopilot_ai.c.
References astar_compare(), AUTO::astar_path, astar_release(), auto_create_astar_node(), auto_destroy_astar_path(), CheckHexBit, CLASS_MECH, CLASS_VEH_GROUND, ClearHexBit, dllist_create_list(), dllist_create_node(), dllist_insert_beginning(), Elevation, astar_node_t::f_score, FindHexRange(), FindXY(), astar_node_t::g_score, getMap(), GetTerrain, astar_node_t::h_score, HEAVY_FOREST, HexOffSet, astar_node_t::hexoffset, HIGHWATER, LIGHT_FOREST, MAP::map_height, MAP::map_width, MapCoordToRealCoord(), AUTO::mapindex, MAPX, MAPY, MBUF_SIZE, MechMove, MechSpecials2, MechType, MechX, MechY, MOUNTAINS, MOVE_HOVER, MOVE_TRACK, AUTO::mynum, rb_delete(), rb_destroy(), rb_exists(), rb_find(), rb_init(), rb_insert(), rb_release(), rb_search(), rb_size(), RealCoordToMapCoord(), ROUGH, SEARCH_FIRST, SetHexBit, WATER, WATERPROOF_TECH, astar_node_t::x, astar_node_t::x_parent, astar_node_t::y, and astar_node_t::y_parent.
Referenced by auto_astar_follow_event(), auto_astar_goto_event(), and auto_astar_roam_event().
00996 { 00997 MAP *map = getMap(autopilot->mapindex); 00998 int found_path = 0; 00999 01000 /* Our bit arrays */ 01001 unsigned char closed_list_bitfield[(MAPX * MAPY) / 8]; 01002 unsigned char open_list_bitfield[(MAPX * MAPY) / 8]; 01003 01004 float x1, y1, x2, y2; /* Floating point vars for real cords */ 01005 short map_x1, map_y1, map_x2, map_y2; /* The actual map 'hexes' */ 01006 int i; 01007 int child_g_score, child_h_score; /* the score values for the child hexes */ 01008 int hexoffset; /* temp int to pass around as the hexoffset */ 01009 01010 /* Our lists using Hag's rbtree */ 01011 /* Using two rbtree's to store the open_list so we can sort two 01012 * different ways */ 01013 rbtree open_list_by_score; /* open list sorted by score */ 01014 rbtree open_list_by_xy; /* open list sorted by hexoffset */ 01015 rbtree closed_list; /* closed list sorted by hexoffset */ 01016 01017 /* Helper node for the final path */ 01018 dllist_node *astar_path_node; 01019 01020 /* Our astar_node helpers */ 01021 astar_node *temp_astar_node; 01022 astar_node *parent_astar_node; 01023 01024 #ifdef DEBUG_ASTAR 01025 /* Log File */ 01026 FILE *logfile; 01027 char log_msg[MBUF_SIZE]; 01028 01029 /* Open the logfile */ 01030 logfile = fopen("astar.log", "a"); 01031 01032 /* Write first message */ 01033 snprintf(log_msg, MBUF_SIZE, 01034 "\nStarting ASTAR Path finding for AI #%d from " 01035 "%d, %d to %d, %d\n", autopilot->mynum, MechX(mech), MechY(mech), 01036 end_x, end_y); 01037 fprintf(logfile, "%s", log_msg); 01038 #endif 01039 01040 /* Zero the bitfields */ 01041 memset(closed_list_bitfield, 0, sizeof(closed_list_bitfield)); 01042 memset(open_list_bitfield, 0, sizeof(open_list_bitfield)); 01043 01044 /* Setup the trees */ 01045 open_list_by_score = rb_init((void *)astar_compare, NULL); 01046 open_list_by_xy = rb_init((void *)astar_compare, NULL); 01047 closed_list = rb_init((void *)astar_compare, NULL); 01048 01049 /* Setup the path */ 01050 /* Destroy any existing path first */ 01051 auto_destroy_astar_path(autopilot); 01052 autopilot->astar_path = dllist_create_list(); 01053 01054 /* Setup the start hex */ 01055 temp_astar_node = 01056 auto_create_astar_node(MechX(mech), MechY(mech), -1, -1, 0, 0); 01057 01058 if(temp_astar_node == NULL) { 01061 #ifdef DEBUG_ASTAR 01062 /* Write Log Message */ 01063 snprintf(log_msg, MBUF_SIZE, 01064 "AI ERROR - Unable to malloc astar node for " "hex %d, %d\n", 01065 MechX(mech), MechY(mech)); 01066 fprintf(logfile, "%s", log_msg); 01067 #endif 01068 01069 } 01070 01071 /* Add start hex to open list */ 01072 rb_insert(open_list_by_score, (void *) temp_astar_node->f_score, 01073 temp_astar_node); 01074 rb_insert(open_list_by_xy, (void *) temp_astar_node->hexoffset, 01075 temp_astar_node); 01076 SetHexBit(open_list_bitfield, temp_astar_node->hexoffset); 01077 01078 #ifdef DEBUG_ASTAR 01079 /* Log it */ 01080 snprintf(log_msg, MBUF_SIZE, "Added hex %d, %d (%d %d) to open list\n", 01081 temp_astar_node->x, temp_astar_node->y, temp_astar_node->g_score, 01082 temp_astar_node->h_score); 01083 fprintf(logfile, "%s", log_msg); 01084 #endif 01085 01086 /* Now loop till we find path */ 01087 while (!found_path) { 01088 01089 /* Check to make sure there is still stuff in the open list 01090 * if not, means we couldn't find a path so quit */ 01091 if(rb_size(open_list_by_score) == 0) { 01092 break; 01093 } 01094 01095 /* Get lowest cost node, then remove it from the open list */ 01096 parent_astar_node = (astar_node *) rb_search(open_list_by_score, 01097 SEARCH_FIRST, NULL); 01098 01099 rb_delete(open_list_by_score, (void *) parent_astar_node->f_score); 01100 rb_delete(open_list_by_xy, (void *) parent_astar_node->hexoffset); 01101 ClearHexBit(open_list_bitfield, parent_astar_node->hexoffset); 01102 01103 #ifdef DEBUG_ASTAR 01104 /* Log it */ 01105 snprintf(log_msg, MBUF_SIZE, "Removed hex %d, %d (%d %d) from open " 01106 "list - lowest cost node\n", 01107 parent_astar_node->x, parent_astar_node->y, 01108 parent_astar_node->g_score, parent_astar_node->h_score); 01109 fprintf(logfile, "%s", log_msg); 01110 #endif 01111 01112 /* Add it to the closed list */ 01113 rb_insert(closed_list, (void *) parent_astar_node->hexoffset, 01114 parent_astar_node); 01115 SetHexBit(closed_list_bitfield, parent_astar_node->hexoffset); 01116 01117 #ifdef DEBUG_ASTAR 01118 /* Log it */ 01119 snprintf(log_msg, MBUF_SIZE, "Added hex %d, %d (%d %d) to closed list" 01120 " - lowest cost node\n", 01121 parent_astar_node->x, parent_astar_node->y, 01122 parent_astar_node->g_score, parent_astar_node->h_score); 01123 fprintf(logfile, "%s", log_msg); 01124 #endif 01125 01126 /* Now we check to see if we added the end hex to the closed list. 01127 * When this happens it means we are done */ 01128 if(CheckHexBit(closed_list_bitfield, HexOffSet(end_x, end_y))) { 01129 found_path = 1; 01130 01131 #ifdef DEBUG_ASTAR 01132 fprintf(logfile, "Found path for the AI\n"); 01133 #endif 01134 01135 break; 01136 } 01137 01138 /* Update open list */ 01139 /* Loop through the hexes around current hex and see if we can add 01140 * them to the open list */ 01141 01142 /* Set the parent hex of the new nodes */ 01143 map_x1 = parent_astar_node->x; 01144 map_y1 = parent_astar_node->y; 01145 01146 /* Going around clockwise direction */ 01147 for(i = 0; i < 360; i += 60) { 01148 01149 /* Map coord to Real */ 01150 MapCoordToRealCoord(map_x1, map_y1, &x1, &y1); 01151 01152 /* Calc new hex */ 01153 FindXY(x1, y1, i, 1.0, &x2, &y2); 01154 01155 /* Real coord to Map */ 01156 RealCoordToMapCoord(&map_x2, &map_y2, x2, y2); 01157 01158 /* Make sure the hex is sane */ 01159 if(map_x2 < 0 || map_y2 < 0 || 01160 map_x2 >= map->map_width || map_y2 >= map->map_height) 01161 continue; 01162 01163 /* Generate hexoffset for the child node */ 01164 hexoffset = HexOffSet(map_x2, map_y2); 01165 01166 /* Check to see if its in the closed list 01167 * if so just ignore it */ 01168 if(CheckHexBit(closed_list_bitfield, hexoffset)) 01169 continue; 01170 01171 /* Check to see if we can enter it */ 01172 if((MechType(mech) == CLASS_MECH) && 01173 (abs(Elevation(map, map_x1, map_y1) 01174 - Elevation(map, map_x2, map_y2)) > 2)) 01175 continue; 01176 01177 if((MechType(mech) == CLASS_VEH_GROUND) && 01178 (abs(Elevation(map, map_x1, map_y1) 01179 - Elevation(map, map_x2, map_y2)) > 1)) 01180 continue; 01181 01182 /* Score the hex */ 01183 /* Right now just assume movement cost from parent to child hex is 01184 * the same (so 100) no matter which dir we go*/ 01186 child_g_score = 100; 01187 01188 /* Now add the g score from the parent */ 01189 child_g_score += parent_astar_node->g_score; 01190 01191 /* Next get range */ 01192 /* Using a varient of the Manhattan method since its perfectly 01193 * logical for us to go diagonally 01194 * 01195 * Basicly just going to get the range, 01196 * and multiply by 100 */ 01199 /* Get the end hex in real coords, using the old variables 01200 * to store the values */ 01201 MapCoordToRealCoord(end_x, end_y, &x1, &y1); 01202 01203 /* Re-using the x2 and y2 values we calc'd for the child hex 01204 * to find the range between the child hex and end hex */ 01205 child_h_score = 100 * FindHexRange(x2, y2, x1, y1); 01206 01207 /* Now add in some modifiers for terrain */ 01208 switch (GetTerrain(map, map_x2, map_y2)) { 01209 case LIGHT_FOREST: 01210 01211 /* Don't bother trying to enter a light forest 01212 * hex unless we can */ 01213 if((MechType(mech) == CLASS_VEH_GROUND) && 01214 (MechMove(mech) != MOVE_TRACK)) 01215 continue; 01216 01217 child_g_score += 50; 01218 break; 01219 case ROUGH: 01220 child_g_score += 50; 01221 break; 01222 case HEAVY_FOREST: 01223 01224 /* Don't bother trying to enter a heavy forest 01225 * hex unless we can */ 01226 if(MechType(mech) == CLASS_VEH_GROUND) 01227 continue; 01228 01229 child_g_score += 100; 01230 break; 01231 case MOUNTAINS: 01232 child_g_score += 100; 01233 break; 01234 case WATER: 01235 01236 /* Don't bother trying to enter a water hex 01237 * unless we can */ 01238 if((MechType(mech) == CLASS_VEH_GROUND) && 01239 (MechMove(mech) != MOVE_HOVER) && !(MechSpecials2(mech) & WATERPROOF_TECH)) 01240 continue; 01241 01242 /* We really don't want them trying to enter water */ 01243 child_g_score += 200; 01244 break; 01245 case HIGHWATER: 01246 01247 /* Don't bother trying to enter a water hex 01248 * unless we can */ 01249 if((MechType(mech) == CLASS_VEH_GROUND) && 01250 (MechMove(mech) != MOVE_HOVER) && !(MechSpecials2(mech) & WATERPROOF_TECH)) 01251 continue; 01252 01253 /* We really don't want them trying to enter water */ 01254 child_g_score += 200; 01255 break; 01256 default: 01257 break; 01258 } 01259 01260 /* Is it already on the openlist */ 01261 if(CheckHexBit(open_list_bitfield, hexoffset)) { 01262 01263 /* Ok need to compare the scores and if necessary recalc 01264 * and change stuff */ 01265 01266 /* Get the node off the open_list */ 01267 temp_astar_node = (astar_node *) rb_find(open_list_by_xy, 01268 (void *) hexoffset); 01269 01270 /* Now compare the 'g_scores' to determine shortest path */ 01271 /* If g_score is lower, this means better path 01272 * from the current parent node */ 01273 if(child_g_score < temp_astar_node->g_score) { 01274 01275 /* Remove from open list */ 01276 rb_delete(open_list_by_score, 01277 (void *) temp_astar_node->f_score); 01278 rb_delete(open_list_by_xy, 01279 (void *) temp_astar_node->hexoffset); 01280 ClearHexBit(open_list_bitfield, 01281 temp_astar_node->hexoffset); 01282 01283 #ifdef DEBUG_ASTAR 01284 /* Log it */ 01285 snprintf(log_msg, MBUF_SIZE, 01286 "Removed hex %d, %d (%d %d) from " 01287 "open list - score recal\n", temp_astar_node->x, 01288 temp_astar_node->y, temp_astar_node->g_score, 01289 temp_astar_node->h_score); 01290 fprintf(logfile, "%s", log_msg); 01291 #endif 01292 01293 /* Recalc score */ 01294 /* H-Score should be the same since the hex doesn't move */ 01295 temp_astar_node->g_score = child_g_score; 01296 temp_astar_node->f_score = temp_astar_node->g_score + 01297 temp_astar_node->h_score; 01298 01299 /* Change parent hex */ 01300 temp_astar_node->x_parent = map_x1; 01301 temp_astar_node->y_parent = map_y1; 01302 01303 /* Will re-add the node below */ 01304 01305 } else { 01306 01307 /* Don't need to do anything so we can skip 01308 * to the next node */ 01309 continue; 01310 01311 } 01312 01313 } else { 01314 01315 /* Node isn't on the open list so we have to create it */ 01316 temp_astar_node = 01317 auto_create_astar_node(map_x2, map_y2, map_x1, map_y1, 01318 child_g_score, child_h_score); 01319 01320 if(temp_astar_node == NULL) { 01323 #ifdef DEBUG_ASTAR 01324 /* Log it */ 01325 snprintf(log_msg, MBUF_SIZE, 01326 "AI ERROR - Unable to malloc astar" 01327 " node for hex %d, %d\n", map_x2, map_y2); 01328 fprintf(logfile, "%s", log_msg); 01329 #endif 01330 01331 } 01332 01333 } 01334 01335 /* Now add (or re-add) the node to the open list */ 01336 01337 /* Hack to check to make sure its score is not already on the open 01338 * list. This slightly skews the results towards nodes found earlier 01339 * then those found later */ 01340 while (1) { 01341 01342 if(rb_exists 01343 (open_list_by_score, (void *) temp_astar_node->f_score)) { 01344 temp_astar_node->f_score++; 01345 01346 #ifdef DEBUG_ASTAR 01347 fprintf(logfile, "Adjusting score for hex %d, %d - same" 01348 " fscore already exists\n", 01349 temp_astar_node->x, temp_astar_node->y); 01350 #endif 01351 01352 } else { 01353 break; 01354 } 01355 01356 } 01357 rb_insert(open_list_by_score, (void *) temp_astar_node->f_score, 01358 temp_astar_node); 01359 rb_insert(open_list_by_xy, (void *) temp_astar_node->hexoffset, 01360 temp_astar_node); 01361 SetHexBit(open_list_bitfield, temp_astar_node->hexoffset); 01362 01363 #ifdef DEBUG_ASTAR 01364 /* Log it */ 01365 snprintf(log_msg, MBUF_SIZE, 01366 "Added hex %d, %d (%d %d) to open list\n", 01367 temp_astar_node->x, temp_astar_node->y, 01368 temp_astar_node->g_score, temp_astar_node->h_score); 01369 fprintf(logfile, "%s", log_msg); 01370 #endif 01371 01372 } /* End of looking for hexes next to us */ 01373 01374 } /* End of looking for path */ 01375 01376 /* We Done lets go */ 01377 01378 /* Lets first see if we found a path */ 01379 if(found_path) { 01380 01381 #ifdef DEBUG_ASTAR 01382 /* Log Message */ 01383 fprintf(logfile, "Building Path from closed list for AI\n"); 01384 #endif 01385 01386 /* Found a path so we need to go through the closed list 01387 * and generate it */ 01388 01389 /* Get the end hex, find its parent hex and work back to 01390 * start hex while building list */ 01391 01392 /* Get end hex from closed list */ 01393 hexoffset = HexOffSet(end_x, end_y); 01394 temp_astar_node = rb_find(closed_list, (void *) hexoffset); 01395 01396 /* Add end hex to path list */ 01397 astar_path_node = dllist_create_node(temp_astar_node); 01398 dllist_insert_beginning(autopilot->astar_path, astar_path_node); 01399 01400 #ifdef DEBUG_ASTAR 01401 /* Log it */ 01402 fprintf(logfile, "Added hex %d, %d to path list\n", 01403 temp_astar_node->x, temp_astar_node->y); 01404 #endif 01405 01406 /* Remove it from closed list */ 01407 rb_delete(closed_list, (void *) temp_astar_node->hexoffset); 01408 01409 #ifdef DEBUG_ASTAR 01410 /* Log it */ 01411 fprintf(logfile, 01412 "Removed hex %d, %d from closed list - path list work\n", 01413 temp_astar_node->x, temp_astar_node->y); 01414 #endif 01415 01416 /* Check if the end hex is the start hex */ 01417 if(!(temp_astar_node->x == MechX(mech) && 01418 temp_astar_node->y == MechY(mech))) { 01419 01420 /* Its not so lets loop through the closed list 01421 * building the path */ 01422 01423 /* Loop */ 01424 while (1) { 01425 01426 /* Get Parent Node Offset */ 01427 hexoffset = HexOffSet(temp_astar_node->x_parent, 01428 temp_astar_node->y_parent); 01429 01433 /* Get Parent Node from closed list */ 01434 parent_astar_node = rb_find(closed_list, (void *) hexoffset); 01435 01436 /* Check if start hex */ 01437 /* If start hex quit */ 01438 if(parent_astar_node->x == MechX(mech) && 01439 parent_astar_node->y == MechY(mech)) { 01440 break; 01441 } 01442 01443 /* Add to path list */ 01444 astar_path_node = dllist_create_node(parent_astar_node); 01445 dllist_insert_beginning(autopilot->astar_path, 01446 astar_path_node); 01447 01448 #ifdef DEBUG_ASTAR 01449 /* Log it */ 01450 fprintf(logfile, "Added hex %d, %d to path list\n", 01451 parent_astar_node->x, parent_astar_node->y); 01452 #endif 01453 01454 /* Remove from closed list */ 01455 rb_delete(closed_list, (void *) parent_astar_node->hexoffset); 01456 01457 #ifdef DEBUG_ASTAR 01458 /* Log it */ 01459 fprintf(logfile, 01460 "Removed hex %d, %d from closed list - path list work\n", 01461 parent_astar_node->x, parent_astar_node->y); 01462 #endif 01463 01464 /* Make parent new child */ 01465 temp_astar_node = parent_astar_node; 01466 01467 } /* End of while loop */ 01468 01469 } 01470 01471 /* Done with the path its cleanup time */ 01472 01473 } 01474 01475 /* Make sure we destroy all the objects we dont need any more */ 01476 01477 #ifdef DEBUG_ASTAR 01478 /* Log Message */ 01479 fprintf(logfile, "Destorying the AI lists\n"); 01480 #endif 01481 01482 /* Destroy the open lists */ 01483 rb_release(open_list_by_score, (void *)astar_release, NULL); 01484 rb_destroy(open_list_by_xy); 01485 01486 /* Destroy the closed list */ 01487 rb_release(closed_list, (void *)astar_release, NULL); 01488 01489 #ifdef DEBUG_ASTAR 01490 /* Close Log file */ 01491 fclose(logfile); 01492 #endif 01493 01494 /* End */ 01495 if(found_path) { 01496 return 1; 01497 } else { 01498 return 0; 01499 } 01500 01501 }
static astar_node* auto_create_astar_node | ( | short | x, | |
short | y, | |||
short | x_parent, | |||
short | y_parent, | |||
short | g_score, | |||
short | h_score | |||
) | [static] |
Definition at line 956 of file autopilot_ai.c.
References astar_node_t::f_score, astar_node_t::g_score, astar_node_t::h_score, astar_node_t::hexoffset, MAPY, astar_node_t::x, astar_node_t::x_parent, astar_node_t::y, and astar_node_t::y_parent.
Referenced by auto_astar_generate_path().
00959 { 00960 00961 astar_node *temp; 00962 temp = malloc(sizeof(astar_node)); 00963 if(temp == NULL) 00964 return NULL; 00965 00966 memset(temp, 0, sizeof(astar_node)); 00967 00968 temp->x = x; 00969 temp->y = y; 00970 temp->x_parent = x_parent; 00971 temp->y_parent = y_parent; 00972 temp->g_score = g_score; 00973 temp->h_score = h_score; 00974 temp->f_score = g_score + h_score; 00975 temp->hexoffset = x * MAPY + y; 00976 00977 return temp; 00978 00979 }
void auto_destroy_astar_path | ( | AUTO * | autopilot | ) |
Definition at line 1535 of file autopilot_ai.c.
References AUTO::astar_path, dllist_destroy_list(), dllist_remove_node_at_pos(), and dllist_size().
Referenced by auto_astar_follow_event(), auto_astar_generate_path(), auto_astar_goto_event(), auto_astar_roam_event(), auto_newautopilot(), and newfreemech().
01536 { 01537 01538 astar_node *temp_astar_node; 01539 01540 /* Make sure there is a path if not quit */ 01541 if(!(autopilot->astar_path)) 01542 return; 01543 01544 /* There is a path lets kill it */ 01545 if(dllist_size(autopilot->astar_path) > 0) { 01546 01547 while (dllist_size(autopilot->astar_path)) { 01548 temp_astar_node = 01549 dllist_remove_node_at_pos(autopilot->astar_path, 1); 01550 free(temp_astar_node); 01551 } 01552 01553 } 01554 01555 /* Finally destroying the path */ 01556 dllist_destroy_list(autopilot->astar_path); 01557 autopilot->astar_path = NULL; 01558 01559 }
Definition at line 331 of file autopilot_ai.c.
References COMBAT_SAFE, Destroyed, enemy_c, enemy_i, enemy_l, enemy_m, enemy_o, FindObjectsData(), MAP::first_free, FlMechRange, LOCInit(), MAP::mechsOnMap, MechStatus, and MechTeam.
Referenced by ai_check_path().
00332 { 00333 MECH *tempMech; 00334 int i; 00335 00336 if(reset) { 00337 for(i = 0; i < enemy_c; i++) { 00338 LOCInit(&enemy_l[i], enemy_m[i]); /* Just reset location */ 00339 enemy_o[i] = 0; 00340 } 00341 return 0; 00342 } 00343 enemy_c = 0; 00344 for(i = 0; i < map->first_free; i++) { 00345 tempMech = FindObjectsData(map->mechsOnMap[i]); 00346 if(!tempMech) 00347 continue; 00348 if(Destroyed(tempMech)) 00349 continue; 00350 if(MechStatus(tempMech) & COMBAT_SAFE) 00351 continue; 00352 if(MechTeam(tempMech) == MechTeam(mech)) 00353 continue; 00354 if(FlMechRange(map, mech, tempMech) > 50.0) 00355 continue; /* Inconsequential */ 00356 /* Something that is _possibly_ unnerving */ 00357 LOCInit(&enemy_l[enemy_c], tempMech); /* Location */ 00358 enemy_m[enemy_c] = tempMech; /* Mech data */ 00359 enemy_i[enemy_c++] = i; 00360 } 00361 return enemy_c; 00362 }
Definition at line 364 of file autopilot_ai.c.
References CLASS_MECH, Destroyed, FindObjectsData(), MAP::first_free, FlMechRange, friend_c, friend_i, friend_l, friend_m, friend_o, LOCInit(), MAP::mechsOnMap, MechTeam, and MechType.
Referenced by ai_check_path().
00365 { 00366 MECH *tempMech; 00367 int i; 00368 00369 if(reset) { 00370 for(i = 0; i < friend_c; i++) { 00371 LOCInit(&friend_l[i], friend_m[i]); /* Just reset location */ 00372 friend_o[i] = 0; 00373 } 00374 return 0; 00375 } 00376 friend_c = 0; 00377 for(i = 0; i < map->first_free; i++) { 00378 tempMech = FindObjectsData(map->mechsOnMap[i]); 00379 if(!tempMech) 00380 continue; 00381 if(Destroyed(tempMech)) 00382 continue; 00383 if(MechTeam(tempMech) != MechTeam(mech)) 00384 continue; 00385 if(MechType(tempMech) != CLASS_MECH) 00386 continue; 00387 if(FlMechRange(map, mech, tempMech) > 50.0) 00388 continue; /* Inconsequential */ 00389 LOCInit(&friend_l[friend_c], tempMech); /* Location */ 00390 friend_m[friend_c] = tempMech; /* Mech data */ 00391 friend_i[friend_c++] = i; 00392 } 00393 return friend_c; 00394 }
Definition at line 303 of file autopilot_ai.c.
References LOC::dh, LOC::ds, LOC::e, LOC::fx, LOC::fy, LOC::h, LOC::lx, LOC::ly, MechDesiredFacing, MechDesiredSpeed, MechElevation, MechFacing, MechFX, MechFY, MechRTerrain, MechSpeed, MechX, MechY, LOC::s, LOC::t, LOC::x, and LOC::y.
Referenced by ai_path_score(), getEnemies(), getFriends(), and mech_snipe_func().
00304 { 00305 l->fx = MechFX(m); 00306 l->fy = MechFY(m); 00307 l->e = MechElevation(m); 00308 l->h = MechFacing(m); 00309 l->dh = MechDesiredFacing(m); 00310 l->s = MechSpeed(m); 00311 l->t = MechRTerrain(m); 00312 l->ds = MechDesiredSpeed(m); 00313 l->x = MechX(m); 00314 l->y = MechY(m); 00315 l->lx = MechX(m); 00316 l->ly = MechY(m); 00317 }
Definition at line 932 of file autopilot_ai.c.
References args, DOCHECK, FindTargetDBREFFromMapNumber(), getMech(), mech_parseattributes(), mech_snipe_func(), multi_weap_sel(), target_mech, and WizRoy.
00933 { 00934 char *args[3]; 00935 dbref d; 00936 00937 DOCHECK(!WizRoy(player), "Permission denied."); 00938 DOCHECK(mech_parseattributes(buffer, args, 3) != 2, 00939 "Please supply target ID _and_ weapon(s) to use"); 00940 DOCHECK((d = 00941 FindTargetDBREFFromMapNumber(mech, args[0])) <= 0, 00942 "Invalid target!"); 00943 target_mech = getMech(d); 00944 multi_weap_sel(mech, player, args[1], 1, mech_snipe_func); 00945 00946 }
Definition at line 908 of file autopilot_ai.c.
References ai_crash(), artillery_round_flight_time(), LOC::fx, LOC::fy, getMap(), LOCInit(), MECH::mapindex, mech_fireweapon(), mech_settarget(), MechFX, MechFY, MechTargX, MechTargY, target_mech, tprintf(), LOC::x, and LOC::y.
Referenced by mech_snipe().
00909 { 00910 /* Simulate mech movements until flight_time <= now */ 00911 int now = 0, crashed = 0; 00912 int flt_time; 00913 LOC t; 00914 MAP *map = getMap(mech->mapindex); 00915 00916 LOCInit(&t, target_mech); 00917 while ((flt_time = 00918 artillery_round_flight_time(MechFX(mech), MechFY(mech), t.fx, 00919 t.fy)) > now) { 00920 if(!crashed) 00921 if(ai_crash(map, target_mech, &t)) 00922 crashed = 1; 00923 now++; 00924 } 00925 /* Fire at t.x, t.y */ 00926 if(MechTargX(mech) != t.x || MechTargY(mech) != t.y) 00927 mech_settarget(player, mech, tprintf("%d %d", t.x, t.y)); 00928 mech_fireweapon(player, mech, tprintf("%d", index)); 00929 return 0; 00930 }
Definition at line 109 of file autopilot_ai.c.
References auto_reply(), and SendAI.
Referenced by ai_check_path().
00110 { 00111 auto_reply(m, msg); 00112 SendAI(msg); 00113 }
float terrain_speed | ( | MECH * | mech, | |
float | tempspeed, | |||
float | maxspeed, | |||
int | terrain, | |||
int | elev | |||
) |
Definition at line 936 of file mech.update.c.
Referenced by ai_crash(), and UpdateSpeed().
00938 { 00939 switch (terrain) { 00940 case SNOW: 00941 case ROUGH: 00942 DECREASE(MP1); 00943 break; 00944 case MOUNTAINS: 00945 DECREASE(MP2); 00946 break; 00947 case LIGHT_FOREST: 00948 if(MechType(mech) != CLASS_BSUIT) 00949 DECREASE(MP1); 00950 break; 00951 case HEAVY_FOREST: 00952 if(MechType(mech) != CLASS_BSUIT) 00953 DECREASE(MP2); 00954 break; 00955 case BRIDGE: 00956 case ROAD: 00957 /* Ground units (wheeled and tracked) get +1 MP moving on paved surface */ 00958 #ifndef BT_MOVEMENT_MODES 00959 if(MechMove(mech) == MOVE_TRACK || MechMove(mech) == MOVE_WHEEL) 00960 #else 00961 if(!(MechStatus2(mech) & SPRINTING) && 00962 (MechMove(mech) == MOVE_TRACK || MechMove(mech) == MOVE_WHEEL)) 00963 #endif 00964 INCREASE_OLD(MP1); 00965 case ICE: 00966 if(MechZ(mech) >= 0) 00967 break; 00968 /* FALLTHRU */ 00969 /* if he's under the ice/bridge, treat as water. */ 00970 case WATER: 00971 if(MechIsBiped(mech) || MechIsQuad(mech)) { 00972 if(elev <= -2) 00973 DECREASE(MP3); 00974 else if(elev == -1) 00975 DECREASE(MP1); 00976 } 00977 break; 00978 } 00979 return tempspeed; 00980 }
int combat_fast_opt[CFAST_COUNT][2] |
Initial value:
{ {0, SP_OPT_FASTER}, {0, SP_OPT_NORM}, {0, SP_OPT_SLOWER}, {-10, SP_OPT_NORM}, {10, SP_OPT_NORM}, {-30, SP_OPT_NORM}, {30, SP_OPT_NORM}, {-60, SP_OPT_NORM}, {60, SP_OPT_NORM} }
Definition at line 97 of file autopilot_ai.c.
Referenced by ai_check_path().
int enemy_c = 0 [static] |
int enemy_i[MAX_MECHS_PER_MAP] [static] |
int enemy_o[MAX_MECHS_PER_MAP] [static] |
int friend_c = 0 [static] |
int friend_i[MAX_MECHS_PER_MAP] [static] |
int friend_o[MAX_MECHS_PER_MAP] [static] |
int move_norm_opt[MNORM_COUNT][2] |
int sp_opt[SP_OPT_C] = { 0, 1, -1 } |
MECH* target_mech [static] |
Definition at line 904 of file autopilot_ai.c.
Referenced by display_mechpref(), mech_mechprefs(), mech_snipe(), and mech_snipe_func().