long computer_check_no_imps(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; SYNCDBG(8,"Starting"); //return _DK_computer_check_no_imps(comp, check); dungeon = comp->dungeon; if (dungeon->num_active_diggers >= check->param1) { return 4; } long able; able = computer_able_to_use_magic(comp, PwrK_MKDIGGER, 0, 1); if (able == 1) { struct Thing *heartng; MapSubtlCoord stl_x, stl_y; heartng = get_player_soul_container(dungeon->owner); stl_x = heartng->mappos.x.stl.num; stl_y = heartng->mappos.y.stl.num; if (xy_walkable(stl_x, stl_y, dungeon->owner)) { if (try_game_action(comp, dungeon->owner, GA_UseMkDigger, 0, stl_x, stl_y, 1, 1) > Lb_OK) { able = 1; } } } return able; }
long computer_check_for_accelerate(struct Computer2 *comp, struct ComputerCheck * check) { static RoomKind workers_in_rooms[] = {RoK_LIBRARY,RoK_LIBRARY,RoK_WORKSHOP,RoK_TRAINING,RoK_SCAVENGER}; struct Thing *thing; long i,n; SYNCDBG(8,"Starting"); //return _DK_computer_check_for_accelerate(comp, check); if (computer_able_to_use_magic(comp, PwrK_SPEEDCRTR, 8, 3) != 1) { return 4; } n = check->param1 % (sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0])); if (n <= 0) n = ACTION_RANDOM(sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0])); for (i=0; i < sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0]); i++) { thing = computer_check_creatures_in_dungeon_rooms_of_kind_for_accelerate(comp, workers_in_rooms[n]); if (!thing_is_invalid(thing)) { SYNCDBG(8,"Cast on thing %d",(int)thing->index); return 1; } n = (n+1) % (sizeof(workers_in_rooms)/sizeof(workers_in_rooms[0])); } return 4; }
long computer_check_for_pretty(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; SYNCDBG(8,"Starting"); dungeon = comp->dungeon; MapSubtlCoord stl_x, stl_y; if (computer_able_to_use_magic(comp, PwrK_HAND, 1, 1) != CTaskRet_Unk1) { return CTaskRet_Unk4; } { long stack_len; stack_len = dungeon->digger_stack_length; if (stack_len <= check->param1 * dungeon->total_area / 100) { return CTaskRet_Unk4; } long n; n = find_in_imp_stack_starting_at(DigTsk_ImproveDungeon, ACTION_RANDOM(stack_len), dungeon); if (n < 0) { return CTaskRet_Unk4; } const struct DiggerStack *dstack; dstack = &dungeon->digger_stack[n]; stl_x = stl_num_decode_x(dstack->stl_num); stl_y = stl_num_decode_y(dstack->stl_num); } struct Thing * creatng; creatng = find_imp_for_pickup(comp, stl_x, stl_y); if (thing_is_invalid(creatng)) { return CTaskRet_Unk4; } if (!create_task_move_creature_to_subtile(comp, creatng, stl_x, stl_y, CrSt_ImpImprovesDungeon)) { return CTaskRet_Unk4; } return CTaskRet_Unk1; }
long computer_check_move_creatures_to_best_room(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; dungeon = comp->dungeon; SYNCDBG(8,"Starting for player %d",(int)dungeon->owner); int num_to_move; num_to_move = check->param1 * dungeon->num_active_creatrs / 100; if (num_to_move <= 0) { SYNCDBG(8,"No player %d creatures to move, active %d percentage %d", (int)dungeon->owner,(int)dungeon->num_active_creatrs,(int)check->param1); return CTaskRet_Unk4; } if (computer_able_to_use_magic(comp, PwrK_HAND, 1, num_to_move) != 1) { return CTaskRet_Unk4; } // If there's already task in progress which uses hand, then don't add more // content of the hand could be used by wrong task by mistake if (is_task_in_progress_using_hand(comp)) { return CTaskRet_Unk4; } if (!create_task_move_creatures_to_room(comp, 0, num_to_move)) { return CTaskRet_Unk4; } SYNCDBG(8,"Added player %d task to move %d creatures to best room",(int)dungeon->owner,(int)num_to_move); return CTaskRet_Unk1; }
long computer_check_move_creatures_to_room(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; struct Room *room; dungeon = comp->dungeon; SYNCDBG(8,"Checking player %d for move to %s", (int)dungeon->owner, room_code_name(check->param2)); int num_to_move; num_to_move = check->param1 * dungeon->num_active_creatrs / 100; if (num_to_move <= 0) { SYNCDBG(8,"No creatures to move, active %d percentage %d", (int)dungeon->num_active_creatrs, (int)check->param1); return CTaskRet_Unk4; } if (computer_able_to_use_magic(comp, PwrK_HAND, 1, num_to_move) != 1) { return CTaskRet_Unk4; } // If there's already task in progress which uses hand, then don't add more // content of the hand could be used by wrong task by mistake if (is_task_in_progress_using_hand(comp)) { return CTaskRet_Unk4; } unsigned long k; long i; k = 0; i = dungeon->room_kind[check->param2]; while (i != 0) { room = room_get(i); if (room_is_invalid(room)) { ERRORLOG("Jump to invalid room detected"); break; } i = room->next_of_owner; // Per-room code if (room->total_capacity > room->used_capacity) { int num_to_move_fit; num_to_move_fit = min(num_to_move, room->total_capacity - room->used_capacity); if (create_task_move_creatures_to_room(comp, room->index, num_to_move_fit)) { SYNCDBG(8,"Added task to move %d creatures to %s index %d", (int)num_to_move_fit,room_code_name(room->kind),(int)room->index); return CTaskRet_Unk1; } } // Per-room code ends k++; if (k > ROOMS_COUNT) { ERRORLOG("Infinite loop detected when sweeping rooms list"); break; } } return CTaskRet_Unk4; }
/** * Quick attack is just putting CTA spell on enemy room. * @param comp * @param check */ long computer_check_for_quick_attack(struct Computer2 *comp, struct ComputerCheck * check) { struct Dungeon *dungeon; SYNCDBG(8,"Starting"); //return _DK_computer_check_for_quick_attack(comp, check); dungeon = comp->dungeon; int creatrs_num; creatrs_num = check->param1 * dungeon->num_active_creatrs / 100; if (check->param3 >= creatrs_num) { return 4; } if (computer_able_to_use_magic(comp, PwrK_CALL2ARMS, 1, 3) != 1) { return 4; } if ((check_call_to_arms(comp) != 1) || is_there_an_attack_task(comp)) { return 4; } struct Room *room; room = get_hated_room_for_quick_attack(comp, check->param3); if (room_is_invalid(room)) { return 4; } struct Coord3d pos; // TODO COMPUTER_PLAYER We should make sure the place of cast is accessible for creatures pos.x.val = subtile_coord_center(room->central_stl_x); pos.y.val = subtile_coord_center(room->central_stl_y); pos.z.val = subtile_coord(1,0); if (check->param3 >= count_creatures_availiable_for_fight(comp, &pos)) { return 4; } if (!create_task_magic_support_call_to_arms(comp, &pos, check->param2, 0, creatrs_num)) { return 4; } output_message(SMsg_EnemyHarassments+ACTION_RANDOM(8), 500, 1); return 1; }
/** * Checks if a computer player has not enough imps. * @param comp * @param check The check structure; param1 is preferred amount of imps, param2 is minimal amount. */ long computer_check_no_imps(struct Computer2 *comp, struct ComputerCheck * check) { if (is_newdig_enabled(comp)) { //workaround for interval seeming to be ignored by from my reconfiguration. //modern computers can handle interval 1 and interval 200 is awfully passive and easy to kill //interval 20 means player-like imp swarms will form while not being excessive //consider making configurable again if *properly* reconfiguring to 20 for all levels except easy beginner levels if (check->turns_interval > 20) check->turns_interval = 20; if (check->param2 < 8) check->param2 = 8; } struct Dungeon *dungeon; SYNCDBG(8,"Starting"); dungeon = comp->dungeon; if (dungeon_invalid(dungeon) || !player_has_heart(dungeon->owner)) { SYNCDBG(7,"Computer players %d dungeon in invalid or has no heart",(int)dungeon->owner); return CTaskRet_Unk4; } long power_price, lowest_price; TbBool diggers_are_cheap; power_price = compute_power_price(dungeon->owner, PwrK_MKDIGGER, 0); lowest_price = compute_lowest_digger_price(dungeon->owner); diggers_are_cheap = power_price <= lowest_price; //see if we can sacrifice imps to reduce price if (gameadd.sacrifice_info.classic_imp_sacrifice) { SYNCDBG(18, "Imp creation power price: %d, lowest: %d", power_price, lowest_price); if (!diggers_are_cheap && dungeon->total_money_owned > power_price //TODO: might need to multiply for safety factor && dungeon_has_room(dungeon, RoK_TEMPLE)) { struct Thing* imp; imp = find_imp_for_sacrifice(comp->dungeon); if (!thing_is_invalid(imp)) { long dist; struct Room* room; room = find_room_nearest_to_position(dungeon->owner, RoK_TEMPLE, &imp->mappos, &dist); if (!room_is_invalid(room)) { if (create_task_move_creature_to_subtile(comp, imp, room->central_stl_x, room->central_stl_y, CrSt_CreatureSacrifice)) return CTaskRet_Unk4; } } } } //regular old imp check after this point long controlled_diggers; TbBool digging_gems; long limit; digging_gems = is_digging_any_gems(dungeon); controlled_diggers = dungeon->num_active_diggers - count_player_diggers_not_counting_to_total(dungeon->owner); //SYNCLOG("controlled diggers of %d = %d, params = %d %d", (int)dungeon->owner, controlled_diggers, check->param1, check->param2); limit = check->param1; if (digging_gems) { if (diggers_are_cheap) limit = max(limit, 50); else limit = max(limit, 20); } if (controlled_diggers >= limit) { return CTaskRet_Unk4; } long able; if ((controlled_diggers == 0 || (controlled_diggers < 3 && (digging_gems || diggers_are_cheap))) && is_power_available(dungeon->owner, PwrK_MKDIGGER)) { //ignore payday and everything else, we need at least 3 imp to play the game able = dungeon->total_money_owned >= compute_power_price(dungeon->owner, PwrK_MKDIGGER, 0); //TODO: recovery could be improved further by looking at length to payday and time it takes to get more money to increase lower bound } else if (controlled_diggers >= check->param2 && !digging_gems) { // We have less than preferred amount, but higher than minimal; allow building if we've got spare money able = computer_able_to_use_magic(comp, PwrK_MKDIGGER, 0, 3 + (controlled_diggers - check->param2)/4); } else { able = computer_able_to_use_magic(comp, PwrK_MKDIGGER, 0, 1); } if (able == CTaskRet_Unk1) { struct Thing *heartng; MapSubtlCoord stl_x, stl_y; heartng = get_player_soul_container(dungeon->owner); stl_x = heartng->mappos.x.stl.num; stl_y = heartng->mappos.y.stl.num; if (xy_walkable(stl_x, stl_y, dungeon->owner)) { if (try_game_action(comp, dungeon->owner, GA_UseMkDigger, 0, stl_x, stl_y, 1, 1) > Lb_OK) { return CTaskRet_Unk1; } } return CTaskRet_Unk1; } return CTaskRet_Unk0; }