//------- Begin of function FirmHarbor::assign_unit -----------// // void FirmHarbor::assign_unit(int unitRecno) { //------- if this is a construction worker -------// if( unit_array[unitRecno]->skill.skill_id == SKILL_CONSTRUCTION ) { set_builder(unitRecno); return; } //---------------------------------------// //if( ship_count==MAX_SHIP_IN_HARBOR ) // return; if(ship_count + (build_unit_id>0) == MAX_SHIP_IN_HARBOR) return; // leave a room for the building unit add_hosted_ship(unitRecno); unit_array[unitRecno]->deinit_sprite(); UnitMarine *unitPtr = (UnitMarine*) unit_array[unitRecno]; unitPtr->extra_move_in_beach = NO_EXTRA_MOVE; unitPtr->deinit_sprite(); //------------------------------------------------// if( firm_array.selected_recno == firm_recno ) info.disp(); }
//-------- Begin of function Nation::ai_sea_travel -------// // // action_x_loc, action_y_loc - location of the destination // // group_unit_array - array of units that will do the sea travel // instance_count - no. of units in the array // // action_para - the action of units after they have arrived the region, // it is one of the following: // // SEA_ACTION_SETTLE - settle into a town // SEA_ACTION_BUILD_CAMP - build and assign to a firm // SEA_ACTION_ASSIGN_TO_FIRM - assign to a firm // SEA_ACTION_MOVE - just move to the destination // (this include moving to the location of a battle field.) // //---------------------------------------------// // // Procedures: // * 1. Locate a ship, build one if cannot locate any. // * 2. Assign the units to the ship. // 3. Move the ship to the destination region. // 4. Units disembark on the coast. // 5. Units move to the destination. // // This function deal with the 1st and 2nd procedures, // when they are finished, action ACTION_AI_SEA_TRAVEL2 // will be added. // //---------------------------------------------// // int Nation::ai_sea_travel(ActionNode* actionNode) { err_when( actionNode->instance_count < 1 || actionNode->instance_count > ActionNode::MAX_ACTION_GROUP_UNIT ); Unit* unitPtr = unit_array[actionNode->group_unit_array[0]]; err_when( unitPtr->nation_recno != nation_recno ); err_when( !unitPtr->is_visible() ); //---- figure out the sea region id which the ship should appear ----// int unitRegionId = world.get_region_id(unitPtr->next_x_loc(), unitPtr->next_y_loc()); int destRegionId = world.get_region_id(actionNode->action_x_loc, actionNode->action_y_loc); int seaRegionId = region_array.get_sea_path_region_id(unitRegionId, destRegionId); //------- 1. try to locate a ship --------// int shipUnitRecno = ai_find_transport_ship(seaRegionId, unitPtr->next_x_loc(), unitPtr->next_y_loc()); if( !shipUnitRecno ) return -1; // must return -1 instead of 0 as the action must be executed immediately otherwise the units will be assigned with other action and the unit list may no longer be valid //---- if this ship is in the harbor, sail it out ----// UnitMarine* unitMarine = (UnitMarine*) unit_array[shipUnitRecno]; if( unitMarine->unit_mode == UNIT_MODE_IN_HARBOR ) { FirmHarbor* firmHarbor = (FirmHarbor*) firm_array[unitMarine->unit_mode_para]; firmHarbor->sail_ship(unitMarine->sprite_recno, COMMAND_AI); } if( !unitMarine->is_visible() ) // no space in the sea for placing the ship return -1; //------ 2. Assign the units to the ship -------// unitMarine->ai_action_id = actionNode->action_id; err_when( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP ); // ##### patch begin Gilbert 5/8 #######// unit_array.assign_to_ship(unitMarine->next_x_loc(), unitMarine->next_y_loc(), 0, actionNode->group_unit_array, actionNode->instance_count, COMMAND_AI, unitMarine->sprite_recno ); // ##### patch end Gilbert 5/8 #######// for( int i=0 ; i<actionNode->instance_count ; i++ ) unit_array[ actionNode->group_unit_array[i] ]->ai_action_id = actionNode->action_id; actionNode->instance_count++; // +1 for the ship actionNode->processing_instance_count = actionNode->instance_count-1; // -1 because when we return 1, it will be increased by 1 automatically actionNode->action_para2 = 0; // reset it, it is set in Nation::action_finished() return 1; }
//--------- Begin of function UnitArray::update_selected_trade_unit_info ---------// // update trade information of trading units if these units are selected // void UnitArray::update_selected_trade_unit_info() { short playerNationRecno = nation_array.player_recno; Unit *unitPtr; UnitMarine *marinePtr; if(remote.is_enable()) { for(int i=size(); i>0; --i) { if(is_deleted(i)) continue; unitPtr = (Unit*)get_ptr(i); if(!unitPtr->is_visible()) continue; switch(unitPtr->unit_id) { case UNIT_CARAVAN: if(mp_is_selected_caravan(i)) ((UnitCaravan*) unitPtr)->update_stop_and_goods_info(); break; case UNIT_VESSEL: case UNIT_CARAVEL: case UNIT_GALLEON: marinePtr = ((UnitMarine*) unitPtr); if(marinePtr->auto_mode && mp_is_selected_ship(i)) marinePtr->update_stop_and_goods_info(); break; default: break; } } } else if(selected_recno && !is_deleted(selected_recno)) { unitPtr = (Unit*)get_ptr(selected_recno); if(unitPtr->nation_recno==playerNationRecno || config.show_ai_info) { switch(unitPtr->unit_id) { case UNIT_CARAVAN: ((UnitCaravan*) unitPtr)->update_stop_and_goods_info(); break; case UNIT_VESSEL: case UNIT_CARAVEL: case UNIT_GALLEON: marinePtr = ((UnitMarine*) unitPtr); if(marinePtr->auto_mode) marinePtr->update_stop_and_goods_info(); break; default: break; } } } }
//------- Begin of function FirmHarbor::think_trade -----------// // int FirmHarbor::think_trade() { //---- see if we have any free ship available ----// Nation* ownNation = nation_array[nation_recno]; UnitMarine* unitMarine = ai_get_free_trade_ship(); if( !unitMarine ) return 0; //--- if this harbor is not linked to any trade firms, return now ---// if( total_linked_trade_firm() == 0 ) return 0; //----- scan for another harbor to trade with this harbor ----// Firm* firmPtr; FirmHarbor* firmHarbor; int i; for( i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) ) continue; firmPtr = firm_array[i]; //### begin alex 24/9 ###// if(firmPtr->firm_id!=FIRM_HARBOR) continue; //#### end alex 24/9 ####// firmHarbor = (FirmHarbor*) firmPtr; if( firmHarbor->total_linked_trade_firm() == 0 ) continue; if( !ownNation->has_trade_ship(firm_recno, i) ) // if there has been any ships trading between these two harbors yet break; } if( i==0 ) return 0; //------ try to set up a sea trade now ------// unitMarine->set_stop( 1, loc_x1, loc_y1, COMMAND_AI); unitMarine->set_stop( 2, firmHarbor->loc_x1, firmHarbor->loc_y1, COMMAND_AI); unitMarine->set_stop_pick_up(1, AUTO_PICK_UP, COMMAND_AI); unitMarine->set_stop_pick_up(2, AUTO_PICK_UP, COMMAND_AI); return 1; }
//------- Begin of function FirmHarbor::should_show_harbor_info -------// // int FirmHarbor::should_show_harbor_info() { if( should_show_info() ) return 1; //--- if any of the ships in the harbor has the spies of the player ---// UnitMarine* unitMarine; for( int i=0 ; i<ship_count ; i++ ) { unitMarine = (UnitMarine*) unit_array[ ship_recno_array[i] ]; if( unitMarine->should_show_info() ) return 1; } return 0; }
//------ Begin of function Nation::ai_sea_attack_target ------// // // <int> targetXLoc, targetYLoc - the location of the target. // int Nation::ai_sea_attack_target(int targetXLoc, int targetYLoc) { UnitMarine* unitMarine; int targetRegionId = world.get_region_id(targetXLoc, targetYLoc); int rc = 0; for( int i=0 ; i<ai_ship_count ; i++ ) { unitMarine = (UnitMarine*) unit_array[ ai_ship_array[i] ]; if( unitMarine->attack_count==0 ) continue; if( !unitMarine->is_ai_all_stop() ) continue; //----- if the ship is in the harbor now -----// if( unitMarine->unit_mode == UNIT_MODE_IN_HARBOR ) { FirmHarbor* firmHarbor = (FirmHarbor*) firm_array[unitMarine->unit_mode_para]; if( firmHarbor->sea_region_id != targetRegionId ) continue; firmHarbor->sail_ship(unitMarine->sprite_recno, COMMAND_AI); } if( !unitMarine->is_visible() ) // no space in the sea for placing the ship continue; if( unitMarine->region_id() != targetRegionId ) continue; //------ order the ship to attack the target ------// unitMarine->attack_unit( targetXLoc, targetYLoc ); rc = 1; } return rc; }
//-------- Begin of function Nation::ai_sea_travel2 -------// // // action_x_loc, action_y_loc - location of the destination // action_para2 - the recno of the ship // (this is set when the ship has moved to the beach, // the function responsible for setting this is Nation::action_finished() ) // //---------------------------------------------// // // Procedures: // 1. Locate a ship, build one if cannot locate any. // 2. Assign the units to the ship. // * 3. Move the ship to the destination region. // 4. Units disembark on the coast. // 5. Units move to the destination. // //---------------------------------------------// // int Nation::ai_sea_travel2(ActionNode* actionNode) { if( unit_array.is_deleted(actionNode->action_para2) ) return -1; UnitMarine* unitMarine = (UnitMarine*) unit_array[actionNode->action_para2]; if( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP ) return -1; if( unitMarine->nation_recno != nation_recno ) return -1; //--------------------------------------------------------// int realDestXLoc, realDestYLoc; // reference vars for returning vars. unitMarine->ship_to_beach( actionNode->action_x_loc, actionNode->action_y_loc, realDestXLoc, realDestYLoc ); // the real destination the ship is moving towards. unitMarine->ai_action_id = actionNode->action_id; return 1; }
//--------- Begin of function Unit::process_ship_to_beach ---------// // process unit action SHIP_TO_BEACH // void Unit::process_ship_to_beach() { //----- action_mode never clear, in_beach to skip idle checking if(cur_action==SPRITE_IDLE) { int shipXLoc = next_x_loc(); int shipYLoc = next_y_loc(); if(shipXLoc==move_to_x_loc && shipYLoc==move_to_y_loc) { if(abs(move_to_x_loc-action_x_loc2)<=2 && abs(move_to_y_loc-action_y_loc2)<=2) { UnitMarine *shipPtr = (UnitMarine*) this; //------------------------------------------------------------------------------// // determine whether extra_move is required //------------------------------------------------------------------------------// switch(shipPtr->extra_move_in_beach) { case NO_EXTRA_MOVE: if(abs(shipXLoc-action_x_loc2)>1 || abs(shipYLoc-action_y_loc2)>1) { err_when(abs(shipXLoc-action_x_loc2)>2 || abs(shipYLoc-action_y_loc2)>2); err_when(result_node_array); shipPtr->extra_move(); } else { //shipPtr->in_beach = 1; shipPtr->extra_move_in_beach = NO_EXTRA_MOVE; //#### trevor 23/10 #####// if(ai_action_id) nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno); //#### trevor 23/10 #####// } break; case EXTRA_MOVING_IN: case EXTRA_MOVING_OUT: //err_when(cur_action!=SPRITE_SHIP_EXTRA_MOVE); break; //#### trevor 23/10 #####// case EXTRA_MOVE_FINISH: if(ai_action_id) nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno); break; //#### trevor 23/10 #####// default: err_here(); break; } } } else reset_action_para(); } else if(cur_action==SPRITE_TURN && is_dir_correct()) set_move(); }
//--------- Begin of function Unit::process_assign_to_ship ---------// // process unit action of assigning units to ship // void Unit::process_assign_to_ship() { err_when(sprite_info->loc_width>1 || sprite_info->loc_height>1); //---------------------------------------------------------------------------// // clear unit's action if situation is changed //---------------------------------------------------------------------------// UnitMarine *shipPtr; if(unit_array.is_deleted(action_para2)) { stop2(); return; // stop the unit as the ship is deleted } else { shipPtr = (UnitMarine*) unit_array[action_para2]; if(shipPtr->nation_recno != nation_recno) { stop2(); return; // stop the unit as the ship's nation_recno != the unit's nation_recno } } if(shipPtr->action_mode2!=ACTION_SHIP_TO_BEACH) { stop2(); // the ship has changed its action return; } int curXLoc = next_x_loc(); int curYLoc = next_y_loc(); int shipXLoc = shipPtr->next_x_loc(); int shipYLoc = shipPtr->next_y_loc(); if(shipPtr->cur_x==shipPtr->next_x && shipPtr->cur_y==shipPtr->next_y && abs(shipXLoc-curXLoc)<=1 && abs(shipYLoc-curYLoc)<=1) { //----------- assign the unit now -----------// if(abs(cur_x-next_x)<sprite_info->speed && abs(cur_y-next_y)<sprite_info->speed) { if(ai_action_id) nation_array[nation_recno]->action_finished(ai_action_id, sprite_recno); stop2(); set_dir(curXLoc, curYLoc, shipXLoc, shipYLoc); shipPtr->load_unit(sprite_recno); return; } } else if(cur_action==SPRITE_IDLE) set_dir(curXLoc, curYLoc, shipPtr->move_to_x_loc, shipPtr->move_to_y_loc); //---------------------------------------------------------------------------// // update location to embark //---------------------------------------------------------------------------// int shipActionXLoc = shipPtr->action_x_loc2; int shipActionYLoc = shipPtr->action_y_loc2; if(abs(shipActionXLoc-action_x_loc2)>1 || abs(shipActionYLoc-action_y_loc2)>1) { if(shipActionXLoc!=action_x_loc2 || shipActionYLoc!=action_y_loc2) { Location *unitLocPtr = world.get_loc(curXLoc, curYLoc); Location *shipActionLocPtr = world.get_loc(shipActionXLoc, shipActionYLoc); if(unitLocPtr->region_id != shipActionLocPtr->region_id) { stop2(); return; } assign_to_ship(shipActionXLoc, shipActionYLoc, action_para2); return; } } }
//-------- Begin of function Nation::ai_find_transport_ship -------// // // Locate a ship for transporting units. // // <int> seaRegionId - region id. of the sea which the ship should appear in. // <int> unitXLoc, unitYLoc - the location of the units to be picked up, // try to select a harbor close to this location. // [int] findBest - whether need to find the best ship or just return // one if there is one found. (default: 1) // // return: <int> the recno of the ship located. // int Nation::ai_find_transport_ship(int seaRegionId, int unitXLoc, int unitYLoc, int findBest) { //------- locate a suitable ship --------// UnitMarine* unitMarine; int curRating, bestRating=0, bestUnitRecno=0; for( int i=0 ; i<ai_ship_count ; i++ ) { unitMarine = (UnitMarine*) unit_array[ ai_ship_array[i] ]; err_when( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP ); if( unitMarine->unit_count > 0 || // if there are already units in the ship unit_res[unitMarine->unit_id]->carry_unit_capacity==0 ) // if the ship does not carry units { continue; } //------- if this ship is in the harbor ---------// if( unitMarine->unit_mode == UNIT_MODE_IN_HARBOR ) { FirmHarbor* firmHarbor = (FirmHarbor*) firm_array[unitMarine->unit_mode_para]; err_when( firmHarbor->firm_id != FIRM_HARBOR ); if( firmHarbor->sea_region_id != seaRegionId ) continue; } //--------- if this ship is on the sea ----------// else { if( !unitMarine->is_ai_all_stop() ) continue; if( unitMarine->region_id() != seaRegionId ) continue; err_when( !unitMarine->is_visible() ); if( !unitMarine->is_visible() ) continue; } //--------- check if the sea region is matched ---------// if( !findBest ) // return immediately when a suitable one is found return unitMarine->sprite_recno; curRating = world.distance_rating( unitXLoc, unitYLoc, unitMarine->next_x_loc(), unitMarine->next_y_loc() ); curRating += (int)unitMarine->hit_points/10 // damage + (int)unitMarine->max_hit_points/10; // ship class if( curRating > bestRating ) { bestRating = curRating; bestUnitRecno = unitMarine->sprite_recno; } } return bestUnitRecno; }
//-------- Begin of function Nation::ai_sea_travel3 -------// // // action_x_loc, action_y_loc - location of the destination // action_para2 - the recno of the ship // //---------------------------------------------// // // Procedures: // 1. Locate a ship, build one if cannot locate any. // 2. Assign the units to the ship. // 3. Move the ship to the destination region. // * 4. Units disembark on the coast. // * 5. Units move to the destination. // //---------------------------------------------// // int Nation::ai_sea_travel3(ActionNode* actionNode) { if( unit_array.is_deleted(actionNode->action_para2) ) return -1; UnitMarine* unitMarine = (UnitMarine*) unit_array[actionNode->action_para2]; if( unit_res[unitMarine->unit_id]->unit_class != UNIT_CLASS_SHIP ) return -1; if( unitMarine->nation_recno != nation_recno ) return -1; //-------- 4. Units disembark on the coast. -------// if( !unitMarine->can_unload_unit() ) return 0; //--- make a copy of the recnos of the unit on the ship ---// short unitRecnoArray[MAX_UNIT_IN_SHIP]; short unitCount; memcpy( unitRecnoArray, unitMarine->unit_recno_array, sizeof(unitRecnoArray) ); unitCount = unitMarine->unit_count; unitMarine->unload_all_units(COMMAND_AI); // unload all units now return 1; // finish the action. /* //---------- 5. Validate all units ----------// for( int i=unitCount-1 ; i>=0 ; i-- ) { if( unit_array.is_deleted( unitRecnoArray[i] ) || unit_array[ unitRecnoArray[i] ]->nation_recno != nation_recno ) { err_when( unitCount > MAX_UNIT_IN_SHIP ); m.del_array_rec( unitRecnoArray, unitCount, sizeof(unitRecnoArray[0]), i+1 ); unitCount--; } } if( unitCount==0 ) return -1; err_when( unitCount < 0 ); //--- 6. Unit actions after they have arrived the destination region ----// int destXLoc = actionNode->action_x_loc; int destYLoc = actionNode->action_y_loc; Location* locPtr = world.get_loc(destXLoc, destYLoc); switch(actionNode->action_para) { case SEA_ACTION_SETTLE: if( locPtr->is_town() && town_array[locPtr->town_recno()]->nation_recno == nation_recno ) { Town *townPtr = town_array[locPtr->town_recno()]; unit_array.assign(townPtr->loc_x1, townPtr->loc_y1, 0, COMMAND_AI, unitRecnoArray, unitCount); // assign to an existing town } else //-- if there is no town there, the unit will try to settle, if there is no space for settle, settle() will just have the units move to the destination { unit_array.settle(destXLoc, destYLoc, 0, COMMAND_AI, unitRecnoArray, unitCount); // settle as a new town } break; case SEA_ACTION_BUILD_CAMP: { Unit* unitPtr = unit_array[ unitRecnoArray[0] ]; unitPtr->build_firm(destXLoc, destYLoc, FIRM_CAMP, COMMAND_AI ); unitPtr->ai_action_id = actionNode->action_id; actionNode->processing_instance_count++; break; } case SEA_ACTION_ASSIGN_TO_FIRM: if( check_firm_ready(destXLoc, destYLoc) ) unit_array.assign(destXLoc, destYLoc, 0, COMMAND_AI, unitRecnoArray, unitCount); break; case SEA_ACTION_MOVE: unit_array.move_to(destXLoc, destYLoc, 0, unitRecnoArray, unitCount, COMMAND_AI); break; case SEA_ACTION_NONE: // just transport them to the specific region and disemark and wait for their own actions break; } //---------- set the action id. of the units ---------// if( actionNode->action_para != SEA_ACTION_BUILD_CAMP ) // with the exception of SEA_ACTION_BUILD_CAMP, units in all other actions are immediately executed { for( int i=unitCount-1 ; i>=0 ; i-- ) { unit_array[ unitRecnoArray[i] ]->ai_action_id = actionNode->action_id; actionNode->processing_instance_count++; } } //---------------------------------------------// actionNode->processing_instance_count--; // decrease it by one as it will be increased in process_action() actionNode->instance_count = actionNode->processing_instance_count+1; // set the instance count so process_action() won't cause error. return 1; */ }