00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00022
00023 #include "crogue.h"
00024
00025
00026 static int count_adjacent_tiles(int x, int y, int type)
00027 {
00028 sint xi, yi;
00029 uint count=0;
00030
00031 for(xi=x-1; xi<=x+1; xi++)
00032 for(yi=y-1; yi<=y+1; yi++)
00033 {
00034 if(xi<0 || yi<0 || xi>=MAPSIZE_X || yi>=MAPSIZE_Y)
00035 continue;
00036 if(w->t[yi][xi].type == type)
00037 count++;
00038 }
00039 return count;
00040 }
00041
00042
00043 #ifdef STUB_FOR_SIZE
00044 void monstmove(sint monst) {}
00045 void webspinner_build(ushort monst, ushort tile_web, ushort tile_floor) {}
00046 void webspinner_cower(ushort monst, ushort tile_web, ushort tile_wall) {}
00047 void monst_chat(ushort monst) {}
00048 #else
00049
00050 void monstmove(sint monst)
00051 {
00052 int flags = w->m[monst].flags;
00053
00054 if( MDESC(monst)->flags & MONSTFLAG_REGENERATE &&
00055 w->m[monst].hps < MDESC(monst)->hps_max)
00056 {
00057 w->m[monst].hps += 1;
00058
00059 if(player_can_see(monst))
00060 message( gettext("The %s regenerates!"), monstname(monst));
00061 }
00062
00063 if( MDESC(monst)->power_max > w->m[monst].power ) {
00064 w->m[monst].power ++;
00065 }
00066
00067 if(flags & (MONST_PARALYZED|MONST_CONFUSED|MONST_PET|MONST_SCARED))
00068 {
00069 if(flags & MONST_PARALYZED) {
00070 if(RANGE(20,1)==1)
00071 w->m[monst].flags &= ~MONST_PARALYZED;
00072 } else if(flags & MONST_CONFUSED) {
00073 monstmoverandomly(monst, 1);
00074 }
00075 else if(flags & MONST_PET) {
00076 pet_move(monst);
00077 }
00078 else if(flags & MONST_SCARED) {
00079 if(!monst_detect_player(monst) && RANGE(5,1)==1)
00080 w->m[monst].flags &= ~MONST_SCARED;
00081 if(w->m[monst].hps*2 > MDESC(monst)->hps_max && RANGE(15,1)==1)
00082 {
00083 if(player_can_see(monst))
00084 message(gettext("The %s regains its courage."),
00085 monstname(monst));
00086 w->m[monst].flags &= ~MONST_SCARED;
00087 }
00088 if(RANGE(4,1)==1)
00089 w->m[monst].hps++;
00090 monstmoveawayfromplayer(monst);
00091 }
00092 }
00093 else if(flags & MONST_ACTIVE)
00094 {
00095 if(flags & MONST_CUST_WHEN_ACTIVE) {
00096 call_aifunc( MDESC(monst)->ai_active, monst );
00097 } else if(flags & (MONST_PEACEFUL|MONST_FRIENDLY)) {
00098 if(flags & MONST_WANDER_WHEN_IDLE)
00099 monstmoverandomly(monst, 0);
00100 else
00101 ;
00102 } else {
00103 if(monstcanmove(monst, w->plr.x, w->plr.y))
00104 monstmovetowardsplayer(monst);
00105 else if(monst_is_aligned_with_plr(monst) &&
00106 monst_attack_type(MTRIGGER_RANGED, monst, 1) )
00107 ;
00108 else if(monst_battle_pet(monst))
00109 ;
00110 else if(!monst_detect_player(monst))
00111 w->m[monst].flags &= ~MONST_ACTIVE;
00112 else if(monst_attack_type(MTRIGGER_SEEN, monst, 1) )
00113 ;
00114 else
00115 monstmovetowardsplayer(monst);
00116 }
00117 }
00118 else
00119 {
00120 if(distancesquare(w->m[monst].x, w->m[monst].y, w->plr.x, w->plr.y)
00121 > 400)
00122 return;
00123 else if(flags & MONST_CUST_WHEN_IDLE) {
00124 call_aifunc( MDESC(monst)->ai_idle, monst );
00125 } else {
00126 if(monst_detect_player(monst))
00127 w->m[monst].flags |= MONST_ACTIVE;
00128 if(flags & MONST_WANDER_WHEN_IDLE) {
00129 if(flags & (MONST_PEACEFUL|MONST_FRIENDLY))
00130 monstmoverandomly(monst, 0);
00131 else
00132 monstmoverandomly(monst, 1);
00133 }
00134 }
00135 }
00136 }
00137
00138
00139
00140
00141
00142
00143
00144 void webspinner_build(ushort monst, ushort tile_web, ushort tile_floor)
00145 {
00146 int x, y, temp;
00147 int xi, yi;
00148 int best = -1;
00149 int best_x = w->m[monst].x;
00150 int best_y = w->m[monst].y;
00151
00152 x = w->m[monst].x + RANGE(2,0) - 1;
00153 y = w->m[monst].y + RANGE(2,0) - 1;
00154
00155 if(w->t[y][x].type == tile_web && monstcanmove(monst, x, y))
00156 {
00157 monstmoveto(monst, x, y);
00158 return;
00159 }
00160
00161 if(RANGE(1,0))
00162 {
00163 for(yi = w->m[monst].y-1; yi <= w->m[monst].y+1; yi++)
00164 for(xi = w->m[monst].x-1; xi <= w->m[monst].x+1; xi++)
00165 {
00166 if(w->t[yi][xi].type != tile_floor)
00167 continue;
00168 if(!monstcanmove(monst, xi, yi))
00169 continue;
00170 temp = count_adjacent_tiles(xi, yi, tile_web);
00171 if(temp > best)
00172 {
00173 best = temp;
00174 best_x = xi;
00175 best_y = yi;
00176 }
00177 }
00178 monstmoveto(monst, best_x, best_y);
00179 w->t[best_y][best_x].type = tile_web;
00180 }
00181 }
00182
00183
00184
00185
00186
00187
00188 void webspinner_cower(ushort monst, ushort tile_web, ushort tile_wall)
00189 {
00190 int best_distance = 1000, best_webbing = 0, temp1, temp2;
00191 int xi, yi;
00192 int target;
00193 int best_x = w->m[monst].x;
00194 int best_y = w->m[monst].y;
00195
00196
00197 if(w->plr.extrinsic[STAT_FLAGS] & STAT_FLAG_ENTANGLED) {
00198 monstmovetowardsplayer(monst);
00199 return;
00200 }
00201
00202 for(yi = w->m[monst].y-1; yi <= w->m[monst].y+1; yi++)
00203 for(xi = w->m[monst].x-1; xi <= w->m[monst].x+1; xi++)
00204 {
00205 if(w->t[yi][xi].type != tile_web)
00206 continue;
00207 target = monstbytile(xi, yi);
00208 if(target>=0 && target != monst)
00209 continue;
00210 temp1 = distancesquare(xi, yi, w->plr.x, w->plr.y);
00211
00212 temp2 = count_adjacent_tiles(xi, yi, tile_web)
00213 + count_adjacent_tiles(xi, yi, tile_wall);
00214 if( temp2>best_webbing ||
00215 (temp1<best_distance && temp2==best_webbing)
00216 )
00217 {
00218 best_distance = temp1;
00219 best_webbing = temp2;
00220 best_x = xi;
00221 best_y = yi;
00222 }
00223 }
00224 monstmoveto(monst, best_x, best_y);
00225 }
00226
00227
00228 void monst_chat(ushort monst)
00229 {
00230 if(monstcanmove(monst, w->plr.x, w->plr.y))
00231 call_chatfunc(MDESC(monst)->chatfunc, monst);
00232 }
00233
00234 #endif
00235