diff --git a/robot.cpp b/robot.cpp index 7dba122..c90bed4 100644 --- a/robot.cpp +++ b/robot.cpp @@ -163,16 +163,10 @@ static void emulate_robot(robot_code &code, robot_regs& r, char robot_id) { break; case ROBOT_CMD_INC_ZONE_code: - // TODO сделать так, чтобы зоны переключались с учетом отключенных зон - if (cmd_arg == ROBOT_ZONE_ETCH) { - std::cout << "robot " << robot_id << " increment etching..." << std::endl; - etching_zone = (short)((etching_zone + 1) & 1); - } else if (cmd_arg == ROBOT_ZONE_GAL) { - std::cout << "robot " << robot_id << " increment galvanic..." << std::endl; - galvanizing_zone = (short)((galvanizing_zone + 1) & 0x07); - } else { - std::cout << "ERROR: R" << robot_id << " INCREMENT ZONE - INVALID ARGUMENT VALUE " << cmd_arg << std::endl; + if (!increment_zone(cmd_arg)) { + std::cout << "WARM: R" << robot_id << " increment zone failed (cmd_arg=" << cmd_arg << ")" << std::endl; } + code.PC++; break; diff --git a/utils.c b/utils.c index 017de19..3b5168b 100644 --- a/utils.c +++ b/utils.c @@ -44,6 +44,116 @@ short get_first_night_zone() { } +short _get_dest_zone(struct barrel *bar) { + if (bar->flags.is_night) { + return ZONE_LOAD_1; + } else { + switch (bar->zone) { + case ZONE_LOAD_2: + // загрузка 2, только в нее можно грузить новые барабаны, нужно обезжиривание + return ZONE_DEGREASING; + + case ZONE_DEGREASING: + // обезжиривание, нужна промывка 1А + return ZONE_WASHING_1A; + + case ZONE_WASHING_1A: + // промывка 1А, нужна промывка 1Б + return ZONE_WASHING_1B; + + case ZONE_WASHING_1B: + // промывка 1Б, нужно травление (зоны 5-6) + if (etching_zone < 0) { + return -1; + } + return (short)(ZONE_ETCHING_1 + etching_zone); + + case ZONE_ETCHING_1: + case ZONE_ETCHING_2: + // травление, нужна промывка 2А + return ZONE_WASHING_2A; + + case ZONE_WASHING_2A: + // промывка 2А, нужна промывка 2Б + return ZONE_WASHING_2B; + + case ZONE_WASHING_2B: + // промывка 2Б, нужно цинкование (зоны 9-16) + if (galvanizing_zone < 0) { + return -1; + } + return (short)(ZONE_GALVANIZING_1 + galvanizing_zone); + + case ZONE_GALVANIZING_1: + case ZONE_GALVANIZING_2: + case ZONE_GALVANIZING_3: + case ZONE_GALVANIZING_4: + case ZONE_GALVANIZING_5: + case ZONE_GALVANIZING_6: + case ZONE_GALVANIZING_7: + case ZONE_GALVANIZING_8: + // TODO перенести эту логику в функцию can_move + // цинкование, требуется чтобы в зонах 17-22 было максимум 2 барабана (3 барабана для этой части линии - максимум) + if (!zone_is_busy(ZONE_WASHING_3A)) { + short count = 0; + // если зона 17 свободна, то диапазон начнется с 3Б + for (short i = ZONE_WASHING_3B; i <= (short)ZONE_UNLOAD; i++) { + if (zone_is_busy(i)) { + count++; + } + } + if (count < 3) { + return ZONE_WASHING_3A; + } + } + return -1; + + case ZONE_WASHING_3A: + // промывка 3А, перекладываем в промывку 3Б + return ZONE_WASHING_3B; + + case ZONE_WASHING_3B: + // это перед пассивацией, требует свободную промывку 4А и на всякий случай свободную пассивацию + if (!zone_is_busy(ZONE_WASHING_4A)) { + return ZONE_PASSIVATION; + } + // это атомарная операция, по идее вносить барабан в пассивацию нельзя + return -1; + + case ZONE_PASSIVATION: + // процесс пассивации, нужна промывка 4A + // чисто теоретически сюда никогда не попадем, но если вдруг выстрелит пусть будет + return ZONE_WASHING_4A; + + case ZONE_WASHING_4A: + // промывка 4А, перекладываем в промывку 4Б + return ZONE_WASHING_4B; + + case ZONE_WASHING_4B: + // последняя промывка в процессе + if (hla_night_mode) { + // TODO изменить логику для ночного режима + return -1; + } else { + return ZONE_UNLOAD; + } + + case ZONE_UNLOAD: + // последняя промывка, нужно разрешение на выгрузку + if (button_unload) { + if (one_robot_mode) { + return ZONE_LOAD_1; + } else { + return hla_exchange_zone; + } + } + break; + } + } + + return -1; +} + // вернет можно ли ехать и главное куда ехать, если можно (нельзя если вернулось значение < 0) // -1 вернет что перемещать нельзя short can_move(struct barrel *bar, char robot_id) { @@ -72,144 +182,9 @@ short can_move(struct barrel *bar, char robot_id) { } // дальше нужно проверить, что можно передвигать бочку - short dest_zone = -1; + short dest_zone = _get_dest_zone(bar); - // если барабан ночной, то надо проверить выгрузку (туда выгружаются ночные барабаны) - if (bar->flags.is_night) { - if (!zone_is_busy(ZONE_LOAD_1)) { - dest_zone = ZONE_LOAD_1; - } - } else { - switch (bar->zone) { - case ZONE_LOAD_2: - // загрузка 2, только в нее можно грузить новые барабаны, нужно обезжиривание - if (!zone_is_busy(ZONE_DEGREASING)) { - dest_zone = ZONE_DEGREASING; - } - break; - - case ZONE_DEGREASING: - // обезжиривание, нужна промывка 1А - if (!zone_is_busy(ZONE_WASHING_1A)) { - dest_zone = ZONE_WASHING_1A; - } - break; - - case ZONE_WASHING_1A: - // промывка 1А, нужна промывка 1Б - if (!zone_is_busy(ZONE_WASHING_1B)) { - dest_zone = ZONE_WASHING_1B; - } - break; - - case ZONE_WASHING_1B: - // промывка 1Б, нужно травление (зоны 5-6) - if (etching_zone < 0) { - break; - } - if (!zone_is_busy((short)(ZONE_ETCHING_1 + etching_zone))) { - dest_zone = (short)(ZONE_ETCHING_1 + etching_zone); - } - break; - - case ZONE_ETCHING_1: - case ZONE_ETCHING_2: - // травление, нужна промывка 2А - if (!zone_is_busy(ZONE_WASHING_2A)) { - dest_zone = ZONE_WASHING_2A; - } - break; - - case ZONE_WASHING_2A: - // промывка 2А, нужна промывка 2Б - if (!zone_is_busy(ZONE_WASHING_2B)) { - dest_zone = ZONE_WASHING_2B; - } - break; - - case ZONE_WASHING_2B: - // промывка 2Б, нужно цинкование (зоны 9-16) - if (galvanizing_zone < 0) { - break; - } - if (!zone_is_busy((short)(ZONE_GALVANIZING_1 + galvanizing_zone))) { - dest_zone = (short)(ZONE_GALVANIZING_1 + galvanizing_zone); - } - break; - - case ZONE_GALVANIZING_1: - case ZONE_GALVANIZING_2: - case ZONE_GALVANIZING_3: - case ZONE_GALVANIZING_4: - case ZONE_GALVANIZING_5: - case ZONE_GALVANIZING_6: - case ZONE_GALVANIZING_7: - case ZONE_GALVANIZING_8: - // цинкование, требуется чтобы в зонах 17-22 было максимум 2 барабана (3 барабана для этой части линии - максимум) - if (!zone_is_busy(ZONE_WASHING_3A)) { - short count = 0; - // если зона 17 свободна, то диапазон начнется с 3Б - for (short i = ZONE_WASHING_3B; i <= (short)ZONE_UNLOAD; i++) { - if (zone_is_busy(i)) { - count++; - } - } - if (count < 3) { - dest_zone = ZONE_WASHING_3A; - } - } - break; - - case ZONE_WASHING_3A: - // промывка 3А, перекладываем в промывку 3Б - if (!zone_is_busy(ZONE_WASHING_3B)) { - dest_zone = ZONE_WASHING_3B; - } - break; - - case ZONE_WASHING_3B: - // это перед пассивацией, требует свободную промывку 4А и на всякий случай свободную пассивацию - if (!zone_is_busy(ZONE_PASSIVATION) && !zone_is_busy(ZONE_WASHING_4A)) { - dest_zone = ZONE_PASSIVATION; - } - // это атомарная операция, по идее вносить барабан в пассивацию нельзя - break; - - case ZONE_PASSIVATION: - // процесс пассивации, нужна промывка 4A - // чисто теоретически сюда никогда не попадем, но если вдруг выстрелит пусть будет - if (!zone_is_busy(ZONE_WASHING_4A)) { - dest_zone = ZONE_WASHING_4A; - } - break; - - case ZONE_WASHING_4A: - // промывка 4А, перекладываем в промывку 4Б - if (!zone_is_busy(ZONE_WASHING_4B)) { - dest_zone = ZONE_WASHING_4B; - } - break; - - case ZONE_WASHING_4B: - // процесс пассивации, нужна промывка 4B (зона 21) (потому что сейчас я в 4A) - if (!zone_is_busy(ZONE_UNLOAD)) { - dest_zone = ZONE_UNLOAD; - } - break; - - case ZONE_UNLOAD: - // последняя промывка, нужно разрешение на выгрузку - if (one_robot_mode && button_unload) { - // нужно промывку загрузку 0 - if (!zone_is_busy(ZONE_LOAD_1)) { - dest_zone = ZONE_LOAD_1; - } - } - break; - } - } - - if (!one_robot_mode) { + if (!one_robot_mode && dest_zone >= 0) { if (robot_id == 1) { // если робот 1, то это старый, который ближе к концу линнии. // Ему нельзя ехать если хоть одна из зон <= max(r2_pos, r2_lock) + кол-во пограничных зон