const player_info* get_player_info() const { return is_human(); }
bool is_local() const { return is_human() || is_ai() || is_idle(); }
struct monst * tamedog(struct monst *mtmp, struct obj *obj) { struct monst *mtmp2; /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */ if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA] || (mtmp->data->mflags3 & M3_WANTSARTI)) return NULL; /* worst case, at least it'll be peaceful; this uses the main RNG because realtime effects means that this won't really sync anyway; this also calls set_malign (thus there's no need for the caller to call it after calling tamedog()) */ msethostility(mtmp, FALSE, TRUE); if (flags.moonphase == FULL_MOON && night() && rn2(6) && obj && mtmp->data->mlet == S_DOG) return NULL; /* If we cannot tame it, at least it's no longer afraid. */ mtmp->mflee = 0; mtmp->mfleetim = 0; /* make grabber let go now, whether it becomes tame or not */ if (mtmp == u.ustuck) { if (Engulfed) expels(mtmp, mtmp->data, TRUE); else if (!(Upolyd && sticks(youmonst.data))) unstuck(mtmp); } /* feeding it treats makes it tamer */ if (mtmp->mtame && obj) { int tasty; if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating && ((tasty = dogfood(mtmp, obj)) == DOGFOOD || (tasty <= ACCFOOD && CONST_EDOG(mtmp)->hungrytime <= moves))) { /* pet will "catch" and eat this thrown food */ if (canseemon(mtmp)) { boolean big_corpse = (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM && mons[obj->corpsenm].msize > mtmp->data->msize); pline("%s catches %s%s", Monnam(mtmp), the(xname(obj)), !big_corpse ? "." : ", or vice versa!"); } else if (cansee(mtmp->mx, mtmp->my)) pline("%s.", Tobjnam(obj, "stop")); /* dog_eat expects a floor object */ place_object(obj, level, mtmp->mx, mtmp->my); dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE); /* eating might have killed it, but that doesn't matter here; a non-null result suppresses "miss" message for thrown food and also implies that the object has been deleted */ return mtmp; } else return NULL; } if (mtmp->mtame || !mtmp->mcanmove || /* monsters with conflicting structures cannot be tamed */ mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion || is_covetous(mtmp->data) || is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(youmonst.data)) || (obj && dogfood(mtmp, obj) >= MANFOOD)) return NULL; if (mtmp->m_id == u.quest_status.leader_m_id) return NULL; /* make a new monster which has the pet extension */ mtmp2 = newmonst(MX_EDOG, mtmp->mnamelth); *mtmp2 = *mtmp; mtmp2->mxtyp = MX_EDOG; mtmp2->mxlth = sizeof (struct edog); if (mtmp->mnamelth) strcpy(NAME_MUTABLE(mtmp2), NAME(mtmp)); initedog(mtmp2); replmon(mtmp, mtmp2); /* `mtmp' is now obsolete */ if (obj) { /* thrown food */ /* defer eating until the edog extension has been set up */ place_object(obj, level, mtmp2->mx, mtmp2->my); /* put on floor */ /* devour the food (might grow into larger, genocided monster) */ if (dog_eat(mtmp2, obj, mtmp2->mx, mtmp2->my, TRUE) == 2) return mtmp2; /* oops, it died... */ /* `obj' is now obsolete */ } if (mtmp2->dlevel == level) newsym(mtmp2->mx, mtmp2->my); if (attacktype(mtmp2->data, AT_WEAP)) { mtmp2->weapon_check = NEED_HTH_WEAPON; mon_wield_item(mtmp2); } return mtmp2; }
player_info* get_player_info() { return is_human(); }
/* fungi will eat even tainted food */ int dogfood(const struct monst *mon, struct obj *obj) { boolean carni = carnivorous(mon->data); boolean herbi = herbivorous(mon->data); const struct permonst *fptr = &mons[obj->corpsenm]; boolean starving; if (is_quest_artifact(obj) || obj_resists(obj, 0, 95)) return obj->cursed ? TABU : APPORT; switch (obj->oclass) { case FOOD_CLASS: if (obj->otyp == CORPSE && ((touch_petrifies(&mons[obj->corpsenm]) && !resists_ston(mon)) || is_rider(fptr))) return TABU; /* Ghouls only eat old corpses... yum! */ if (mon->data == &mons[PM_GHOUL]) return (obj->otyp == CORPSE && peek_at_iced_corpse_age(obj) + 50L <= moves) ? DOGFOOD : TABU; if (!carni && !herbi) return obj->cursed ? UNDEF : APPORT; /* a starving pet will eat almost anything */ starving = (mon->mtame && !mon->isminion && CONST_EDOG(mon)->mhpmax_penalty); switch (obj->otyp) { case TRIPE_RATION: case MEATBALL: case MEAT_RING: case MEAT_STICK: case HUGE_CHUNK_OF_MEAT: return carni ? DOGFOOD : MANFOOD; case EGG: if (touch_petrifies(&mons[obj->corpsenm]) && !resists_ston(mon)) return POISON; return carni ? CADAVER : MANFOOD; case CORPSE: if ((peek_at_iced_corpse_age(obj) + 50L <= moves && obj->corpsenm != PM_LIZARD && obj->corpsenm != PM_LICHEN && mon->data->mlet != S_FUNGUS) || (acidic(&mons[obj->corpsenm]) && !resists_acid(mon)) || (poisonous(&mons[obj->corpsenm]) && !resists_poison(mon))) return POISON; else if (vegan(fptr)) return herbi ? CADAVER : MANFOOD; else return carni ? CADAVER : MANFOOD; case CLOVE_OF_GARLIC: return (is_undead(mon->data) ? TABU : ((herbi || starving) ? ACCFOOD : MANFOOD)); case TIN: return metallivorous(mon->data) ? ACCFOOD : MANFOOD; case APPLE: case CARROT: return herbi ? DOGFOOD : starving ? ACCFOOD : MANFOOD; case BANANA: return ((mon->data->mlet == S_YETI) ? DOGFOOD : ((herbi || starving) ? ACCFOOD : MANFOOD)); case K_RATION: case C_RATION: case CRAM_RATION: case LEMBAS_WAFER: case FOOD_RATION: if (is_human(mon->data) || is_elf(mon->data) || is_dwarf(mon->data) || is_gnome(mon->data) || is_orc(mon->data)) return ACCFOOD; default: if (starving) return ACCFOOD; return (obj->otyp > SLIME_MOLD ? (carni ? ACCFOOD : MANFOOD) : (herbi ? ACCFOOD : MANFOOD)); } default: if (obj->otyp == AMULET_OF_STRANGULATION || obj->otyp == RIN_SLOW_DIGESTION) return TABU; if (hates_silver(mon->data) && objects[obj->otyp].oc_material == SILVER) return TABU; if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj)) return ACCFOOD; if (metallivorous(mon->data) && is_metallic(obj) && (is_rustprone(obj) || mon->data != &mons[PM_RUST_MONSTER])) { /* Non-rustproofed ferrous based metals are preferred. */ return (is_rustprone(obj) && !obj->oerodeproof) ? DOGFOOD : ACCFOOD; } if (!obj->cursed && obj->oclass != BALL_CLASS && obj->oclass != CHAIN_CLASS) return APPORT; /* fall into next case */ case ROCK_CLASS: return UNDEF; } }
//--------- Begin of function Unit::init ---------// // // <int> unitId - the id. of the unit // <int> nationRecno - the recno of nation // [int] rankId - rank id. of the unit (none for non-human unit) // [int] unitLoyalty - loyalty of the unit (none for non-human unit) // [int] startXLoc, startYLoc - the starting location of the unit // (if startXLoc < 0, this is a unit for hire, and is not a unit of the game yet. init_sprite() won't be called for this unit) // (default: -1, -1) // // Note: sprite_recno must be initialized first before calling Unit::init() // void Unit::init(int unitId, int nationRecno, int rankId, int unitLoyalty, int startXLoc, int startYLoc) { //------------ set basic vars -------------// nation_recno = (char) nationRecno; rank_id = rankId; // rank_id must be initialized before init_unit_id() as init_unit_id() may overwrite it if( rank_id == RANK_GENERAL || rank_id == RANK_KING ) { err_when( team_info ); team_info = (TeamInfo*) mem_add( sizeof(TeamInfo) ); memset( team_info, 0, sizeof(TeamInfo) ); } init_unit_id(unitId); race_id = (char) unit_res[unit_id]->race_id; //------- init unit name ---------// if( is_human() && unit_id != UNIT_WAGON ) { name_id = race_res[race_id]->get_new_name_id(); } else if( is_monster() ) { name_id = monster_res.get_new_name_id(); } else //---- init non-human unit series no. ----// { if( nation_recno ) name_id = ++nation_array[nation_recno]->last_unit_name_id_array[unit_id-1]; else name_id = 0; } // ###### begin Gilbert 23/2 ######// unique_id = misc.rand_long(); // ###### end Gilbert 23/2 ######// //---------- init other vars ----------// err_when( unitLoyalty < 0 || unitLoyalty > 100 ); loyalty = unitLoyalty; // ##### begin Gilbert 29/5 ########// if( is_die_after_attack() ) // behavior_mode = UNIT_STAND_GROUND; // bee die after attack, so don't waste his life behavior_mode = UNIT_DEFENSIVE; // bee die after attack, so don't waste his life else behavior_mode = UNIT_AGGRESSIVE; // the default mode is aggressive // ##### end Gilbert 29/5 ########// //--------- init skill, and skill potential ---------// skill.init(unit_id, 100); set_combat_level(-1); hit_points = (float) max_hit_points(); //------ initialize the base Sprite class -------// if( startXLoc >= 0 ) init_sprite( startXLoc, startYLoc ); else cur_x = -1; //-------------- update loyalty -------------// update_loyalty(); //--------------- init AI info -------------// init_ai(); //----------- init derived class ----------// init_derived(); set_combat_level(-1); }
//--------- Begin of function Unit::deinit ---------// // void Unit::deinit() { //---------- free up team_info ----------// if( team_info ) { mem_del(team_info); team_info = NULL; } //---------------------------------------// // ####### begin Gilbert 22/3 ########// if( sys.quick_exit_flag() ) { if( game.is_campaign_mode() ) { // if in campaign mode, free name before exit if( name_id ) { if( is_human() && unit_id != UNIT_WAGON ) { if( name_id ) race_res[race_id]->free_name_id( name_id ); } else if( is_monster() ) { if( name_id ) monster_res.free_name_id( name_id ); } else //---- init non-human unit series no. ----// { } name_id = 0; } } return; } // ####### end Gilbert 22/3 ########// //---------------------------------------// err_when( unit_array.is_truly_deleted(sprite_recno) ); if( !unit_id ) return; // ######### begin Gilbert 23/2 #######// // -------- update win/lose condition or die -------// if( hit_points <= 0.0f || cur_action == SPRITE_DIE ) { game.update_condition_on_killed( unique_id ); } // ######### end Gilbert 23/2 #######// //--------- drop item -----------// if( !sys.signal_exit_flag && item.id ) { drop_item(COMMAND_AUTO); } //-------- if this is a king --------// if( !sys.signal_exit_flag && nation_recno ) { if( rank_id == RANK_KING ) // check nation_recno because monster kings will die also. { king_die(); err_when( unit_array.is_truly_deleted(sprite_recno) ); } else if( rank_id == RANK_GENERAL ) { general_die(); err_when( unit_array.is_truly_deleted(sprite_recno) ); } } // ####### begin Gilbert 12/3 #######// // -------- free name id after general_die, which reads name_id ---------// if( name_id ) { if( is_human() && unit_id != UNIT_WAGON ) { if( name_id ) race_res[race_id]->free_name_id( name_id ); } else if( is_monster() ) { if( name_id ) monster_res.free_name_id( name_id ); } else //---- init non-human unit series no. ----// { } name_id = 0; } // ####### end Gilbert 12/3 #######// //---- if this is a general, deinit its link with its soldiers ----// // // We do not use team_info because monsters and rebels also use // leader_unit_recno and they do not use keep the member info // in team_info. // //-----------------------------------------------------------------// if( rank_id == RANK_GENERAL || rank_id == RANK_KING ) { for( int i=unit_array.size() ; i>0 ; i-- ) { if( unit_array.is_deleted(i) ) continue; if( unit_array[i]->leader_unit_recno == sprite_recno ) unit_array[i]->leader_unit_recno = 0; } } //----- if this is a unit on a ship ------// if( unit_mode == UNIT_MODE_ON_SHIP ) { err_here(); /* if( !unit_array.is_deleted(unit_mode_para) ) // the ship may have been destroyed at the same time. Actually when the ship is destroyed, all units onboard are killed and this function is called. { Unit* unitPtr = unit_array[unit_mode_para]; err_when( unit_res[unitPtr->unit_id]->unit_class != UNIT_CLASS_SHIP ); ((UnitMarine*)unitPtr)->del_unit(sprite_recno); } */ } //----- if this is a ship in the harbor -----// else if( unit_mode == UNIT_MODE_IN_HARBOR ) { err_here(); /* if( !firm_array.is_deleted(unit_mode_para) ) // the ship may have been destroyed at the same time. Actually when the ship is destroyed, all firms onboard are killed and this function is called. { Firm* firmPtr = firm_array[unit_mode_para]; err_when( firmPtr->firm_id != FIRM_HARBOR ); ((FirmHarbor*)firmPtr)->del_hosted_ship(sprite_recno); } */ } //----- if this unit is a constructor in a firm -------// else if( unit_mode == UNIT_MODE_CONSTRUCT_FIRM ) { err_when( firm_array[unit_mode_para]->builder_recno != sprite_recno ); firm_array[unit_mode_para]->builder_recno = 0; } //----- if this unit is a constructor in a town -------// else if( unit_mode == UNIT_MODE_CONSTRUCT_TOWN ) { err_when( town_array[unit_mode_para]->builder_recno != sprite_recno ); town_array[unit_mode_para]->builder_recno = 0; } //-------- if this is a spy ---------// if( spy_recno ) { spy_array.del_spy( spy_recno ); spy_recno = 0; } //---------- reset command ----------// if( power.command_unit_recno == sprite_recno ) power.reset_command(); //-----------------------------------// deinit_unit_id(); //----- if cur_x == -1, the unit has not yet been hired -----// if( cur_x >= 0 ) deinit_sprite(); // ##### patch begin Gilbert 6/10 ######// else if( selected_flag ) // caravan may be deinit_sprite(1) and keep selected, now unselect { int curSelected = unit_array.selected_recno == sprite_recno; // if it is currently selected unit, reset selected_recno deselect(); if( curSelected && !sys.signal_exit_flag ) info.disp(); } // ##### patch end Gilbert 6/10 ######// //--------------- deinit AI info -------------// deinit_ai(); //-------------- reset unit_id ---------------// unit_id = 0; }
//--------- Begin of function Nation::think_destroy_raw_site_guard --------// // int Nation::think_destroy_raw_site_guard() { Site* sitePtr; Location* locPtr; Unit* unitPtr; for( int i=site_array.size() ; i>0 ; i-- ) { if( site_array.is_deleted(i) ) continue; sitePtr = site_array[i]; //--- if there is already a mine built on this raw site ---// if( sitePtr->has_mine ) continue; //----- if there is a unit standing on this site -----// locPtr = world.get_loc( sitePtr->map_x_loc, sitePtr->map_y_loc ); if( !locPtr->unit_recno(UNIT_LAND) ) continue; unitPtr = unit_array[ locPtr->unit_recno(UNIT_LAND) ]; if( unitPtr->cur_action != SPRITE_IDLE ) // only attack if this unit is idle continue; if( unitPtr->nation_recno == nation_recno ) // don't attack our own units continue; //------ check if we have a presence in this region ----// if( is_human() && base_town_count_in_region(sitePtr->region_id) == 0 ) continue; //------ check the relationship with this unit ------// // // If we are friendly with this nation, don't attack it. // //---------------------------------------------------// if( get_relation_status(unitPtr->nation_recno) >= RELATION_FRIENDLY ) continue; //--------- attack the enemy unit ---------// int hasWar; int enemyCombatLevel = mobile_defense_combat_level( sitePtr->map_x_loc, sitePtr->map_y_loc, unitPtr->nation_recno, 1, hasWar ); if( enemyCombatLevel == - 1 ) // a war is going on here, don't attack this target continue; if( ai_attack_target(sitePtr->map_x_loc, sitePtr->map_y_loc, enemyCombatLevel, 0, 0, 0, 0, 1) ) // 1-use all camps return 1; } return 0; }
//----- Begin of function Nation::consider_accept_surrender_request -----// // // Consider accepting the cash offer and sell the throne to another kingdom. // // talkMsg->talk_para1 - the amount offered. // int Nation::consider_accept_surrender_request(TalkMsg* talkMsg) { Nation* nationPtr = nation_array[talkMsg->from_nation_recno]; int offeredAmt = talkMsg->talk_para1 * 10; // *10 to restore its original value which has been divided by 10 to cope with <short> upper limit //--- if the nation does not have any towns, camps or generals, it will have a larger tendency to surrender. ---// int weakNation = (ai_town_count==0 && ai_camp_count==0 && ai_general_count==0); //---- only surrender to nations of the same nationality or Fryhtan species ----// if( is_human() != nationPtr->is_human() ) return 0; //---- don't surrender to the player if the player is already the most powerful nation ---// if( !weakNation && !nationPtr->is_ai() && config.ai_aggressiveness >= OPTION_HIGH ) { if( nation_array.max_overall_nation_recno == nationPtr->nation_recno ) return 0; } //--- if we are running out of cash, ignore all normal thinking ---// if( !(cash < 100 && profit_365days() < 0) && !weakNation ) { //----- never surrender to a weaker nation ------// if( nationPtr->overall_rank_rating() < overall_rank_rating() ) return 0; //------ don't surrender if we are still strong -----// if( overall_rank_rating() > 30 + pref_peacefulness/4 ) // 30 to 55 return 0; //---- don't surrender if our cash is more than the amount they offered ----// if( offeredAmt < cash * (75+pref_cash_reserve/2) / 100 ) // 75% to 125% return 0; //-- if there are only two nations left, don't surrender if we still have some power --// if( nation_array.nation_count == 2 ) { if( overall_rank_rating() > 20 - 10 * pref_military_courage / 100 ) return 0; } } //-------------------------------------// int surrenderToRating = ai_surrender_to_rating(talkMsg->from_nation_recno); surrenderToRating += 100 * offeredAmt / 10000; int acceptRating = overall_rank_rating()*13 + 100; //------ AI aggressiveness effects -------// switch( config.ai_aggressiveness ) { case OPTION_HIGH: if( nationPtr->is_ai() ) // tend to accept AI kingdom offer easier acceptRating -= 75; else acceptRating += 75; break; case OPTION_VERY_HIGH: if( nationPtr->is_ai() ) // tend to accept AI kingdom offer easier acceptRating -= 150; else acceptRating += 150; break; } return surrenderToRating > acceptRating; }