From a2253617cfaba6706ffb3e9dea3592bdbc4ff8f1 Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Tue, 19 Aug 2014 11:58:58 +0200 Subject: [PATCH 1/2] Makes it possible for the AI to make station wide announcements. Improved AI verb handling in case of death/restoration. --- code/defines/procs/captain_announce.dm | 11 +- code/game/machinery/computer/ai_core.dm | 2 + code/game/machinery/computer/aifixer.dm | 5 +- code/modules/mob/living/silicon/ai/ai.dm | 141 +++++++++++++----- code/modules/mob/living/silicon/ai/death.dm | 1 + .../mob/living/silicon/ai/freelook/eye.dm | 4 +- code/modules/mob/living/silicon/ai/laws.dm | 3 +- code/modules/mob/living/silicon/ai/life.dm | 4 + code/modules/mob/transform_procs.dm | 2 +- 9 files changed, 121 insertions(+), 52 deletions(-) diff --git a/code/defines/procs/captain_announce.dm b/code/defines/procs/captain_announce.dm index 9b91705ea56..092d297a2de 100644 --- a/code/defines/procs/captain_announce.dm +++ b/code/defines/procs/captain_announce.dm @@ -1,5 +1,6 @@ -/proc/captain_announce(var/text) - world << "

Priority Announcement

" - world << "[html_encode(text)]" - world << "
" - +/proc/captain_announce(message as text, title = "Priority Announcement", announcer = "") + world << "

[html_encode(title)]

" + world << "[html_encode(message)]" + if(announcer) + world << " -[html_encode(announcer)]" + world << "
" \ No newline at end of file diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 0946e7943cf..1c70db6d675 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -231,6 +231,7 @@ That prevents a few funky behaviors. new /obj/structure/AIcore/deactivated(T.loc) T.aiRestorePowerRoutine = 0 T.control_disabled = 1 + T.aiRadio.disabledAi = 1 T.loc = C C.AI = T T.cancel_camera() @@ -245,6 +246,7 @@ That prevents a few funky behaviors. var/mob/living/silicon/ai/A = locate() in C//I love locate(). Best proc ever. if(A)//If AI exists on the card. Else nothing since both are empty. A.control_disabled = 0 + A.aiRadio.disabledAi = 0 A.loc = T.loc//To replace the terminal. C.icon_state = "aicard" C.name = "inteliCard" diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index 1b6ff558875..fc636c879a3 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -87,13 +87,14 @@ src.occupant.adjustToxLoss(-1) src.occupant.adjustBruteLoss(-1) src.occupant.updatehealth() - if (src.occupant.health >= 0 && src.occupant.stat == 2) - src.occupant.stat = 0 + if (src.occupant.health >= 0 && src.occupant.stat == DEAD) + src.occupant.stat = CONSCIOUS src.occupant.lying = 0 dead_mob_list -= src.occupant living_mob_list += src.occupant src.overlays -= image('icons/obj/computer.dmi', "ai-fixer-404") src.overlays += image('icons/obj/computer.dmi', "ai-fixer-full") + src.occupant.add_ai_verbs() src.updateUsrDialog() sleep(10) src.active = 0 diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index ff0c13c2fb7..758883dfff7 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -1,4 +1,28 @@ +#define AI_CHECK_WIRELESS 1 +#define AI_CHECK_RADIO 2 + var/list/ai_list = list() +var/list/ai_verbs_default = list( + /mob/living/silicon/ai/proc/ai_announcement, + /mob/living/silicon/ai/proc/ai_call_shuttle, + // /mob/living/silicon/ai/proc/ai_recall_shuttle, + /mob/living/silicon/ai/proc/ai_camera_track, + /mob/living/silicon/ai/proc/ai_camera_list, + /mob/living/silicon/ai/proc/ai_goto_location, + /mob/living/silicon/ai/proc/ai_remove_location, + /mob/living/silicon/ai/proc/ai_hologram_change, + /mob/living/silicon/ai/proc/ai_network_change, + /mob/living/silicon/ai/proc/pick_icon, + /mob/living/silicon/ai/proc/ai_roster, + /mob/living/silicon/ai/proc/ai_statuschange, + /mob/living/silicon/ai/proc/ai_store_location, + /mob/living/silicon/ai/proc/checklaws, + /mob/living/silicon/ai/proc/control_integrated_radio, + /mob/living/silicon/ai/proc/core, + /mob/living/silicon/ai/proc/show_laws_verb, + /mob/living/silicon/ai/proc/toggle_acceleration, + /mob/living/silicon/ai/proc/toggle_camera_light +) //Not sure why this is necessary... /proc/AutoUpdateAI(obj/subject) @@ -53,19 +77,12 @@ var/list/ai_list = list() var/datum/trackable/track = null var/last_announcement = "" -proc/add_ai_verbs(var/mob/M) - M.verbs += /mob/living/silicon/ai/proc/ai_call_shuttle - M.verbs += /mob/living/silicon/ai/proc/ai_camera_track - M.verbs += /mob/living/silicon/ai/proc/ai_camera_list - M.verbs += /mob/living/silicon/ai/proc/ai_goto_location - M.verbs += /mob/living/silicon/ai/proc/ai_remove_location - M.verbs += /mob/living/silicon/ai/proc/ai_hologram_change - M.verbs += /mob/living/silicon/ai/proc/ai_network_change - M.verbs += /mob/living/silicon/ai/proc/ai_roster - M.verbs += /mob/living/silicon/ai/proc/ai_statuschange - M.verbs += /mob/living/silicon/ai/proc/ai_store_location - M.verbs += /mob/living/silicon/ai/proc/control_integrated_radio - M.verbs += /mob/living/silicon/ai/proc/toggle_camera_light +/mob/living/silicon/ai/proc/add_ai_verbs() + src.verbs += ai_verbs_default + +/mob/living/silicon/ai/proc/remove_ai_verbs() + src.verbs -= ai_verbs_default + /mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0) var/list/possibleNames = ai_names @@ -95,8 +112,6 @@ proc/add_ai_verbs(var/mob/M) else laws = new base_law_type - verbs += /mob/living/silicon/ai/proc/show_laws_verb - aiPDA = new/obj/item/device/pda/ai(src) aiPDA.owner = name aiPDA.ownjob = "AI" @@ -193,7 +208,7 @@ proc/add_ai_verbs(var/mob/M) if(powered_ai.anchored) use_power = 2 -/mob/living/silicon/ai/verb/pick_icon() +/mob/living/silicon/ai/proc/pick_icon() set category = "AI Commands" set name = "Set AI Core Display" if(stat || aiRestorePowerRoutine) @@ -288,20 +303,43 @@ proc/add_ai_verbs(var/mob/M) set name = "Show Crew Manifest" show_station_manifest() +/mob/living/silicon/ai/var/message_cooldown = 0 +/mob/living/silicon/ai/proc/ai_announcement() + set category = "AI Commands" + set name = "Make Station Announcement" + + if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) + return + + if(message_cooldown) + src << "Please allow one minute to pass between announcements." + return + var/input = stripped_input(usr, "Please write a message to announce to the station crew.", "A.I. Announcement") + if(!input) + return + + if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO)) + return + + captain_announce(input, "A.I. Announcement", src.name) + log_say("[key_name(usr)] has made an AI announcement: [input]") + message_admins("[key_name_admin(usr)] has made an AI announcement.", 1) + message_cooldown = 1 + spawn(600)//One minute cooldown + message_cooldown = 0 + /mob/living/silicon/ai/proc/ai_call_shuttle() set category = "AI Commands" set name = "Call Emergency Shuttle" - if(src.stat == 2) - src << "You can't call the shuttle because you are dead!" + + if(check_unable(AI_CHECK_WIRELESS)) return - if(istype(usr,/mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = src - if(AI.control_disabled) - usr << "Wireless control is disabled!" - return var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No") + if(check_unable(AI_CHECK_WIRELESS)) + return + if(confirm == "Yes") call_shuttle_proc(src) @@ -311,20 +349,19 @@ proc/add_ai_verbs(var/mob/M) if(C) C.post_status("shuttle") - return - -/mob/living/silicon/ai/proc/ai_cancel_call() +/mob/living/silicon/ai/proc/ai_recall_shuttle() set category = "AI Commands" - if(src.stat == 2) - src << "You can't send the shuttle back because you are dead!" + set name = "Recall Emergency Shuttle" + + if(check_unable(AI_CHECK_WIRELESS)) return - if(istype(usr,/mob/living/silicon/ai)) - var/mob/living/silicon/ai/AI = src - if(AI.control_disabled) - src << "Wireless control is disabled!" - return - cancel_call_proc(src) - return + + var/confirm = alert("Are you sure you want to recall the shuttle?", "Confirm Shuttle Recall", "Yes", "No") + if(check_unable(AI_CHECK_WIRELESS)) + return + + if(confirm == "Yes") + cancel_call_proc(src) /mob/living/silicon/ai/check_eye(var/mob/user as mob) if (!current) @@ -534,7 +571,7 @@ proc/add_ai_verbs(var/mob/M) src.cameraFollow = null - if (!C || stat == 2) //C.can_use()) + if (!C || stat == DEAD) //C.can_use()) return 0 if(!src.eyeobj) @@ -587,8 +624,7 @@ proc/add_ai_verbs(var/mob/M) src.cameraFollow = null var/cameralist[0] - if(usr.stat == 2) - usr << "You can't change your camera network because you are dead!" + if(check_unable()) return var/mob/living/silicon/ai/U = usr @@ -631,9 +667,9 @@ proc/add_ai_verbs(var/mob/M) set category = "AI Commands" set name = "AI Status" - if(usr.stat == 2) - usr <<"You cannot change your emotional status because you are dead!" + if(check_unable(AI_CHECK_WIRELESS)) return + var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Surprised", "Sad", "Upset", "Angry", "Awesome", "BSOD", "Blank", "Problems?", "Facepalm", "Friend Computer") var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions for (var/obj/machinery/M in machines) //change status @@ -656,6 +692,9 @@ proc/add_ai_verbs(var/mob/M) set desc = "Change the default hologram available to AI to something else." set category = "AI Commands" + if(check_unable()) + return + var/input if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member") @@ -704,6 +743,9 @@ proc/add_ai_verbs(var/mob/M) set desc = "Toggles the light on the camera the AI is looking through." set category = "AI Commands" + if(check_unable()) + return + camera_light_on = !camera_light_on src << "Camera lights [camera_light_on ? "activated" : "deactivated"]." if(!camera_light_on) @@ -766,6 +808,25 @@ proc/add_ai_verbs(var/mob/M) set desc = "Allows you to change settings of your radio." set category = "AI Commands" + if(check_unable(AI_CHECK_RADIO)) + return + src << "Accessing Subspace Transceiver control..." if (src.aiRadio) src.aiRadio.interact(src) + +/mob/living/silicon/ai/proc/check_unable(var/flags = 0) + if(stat == DEAD) + usr << "\red You are dead!" + return 1 + + if((flags & AI_CHECK_WIRELESS) && src.control_disabled) + usr << "\red Wireless control is disabled!" + return 1 + if((flags & AI_CHECK_RADIO) && src.aiRadio.disabledAi) + src << "\red System Error - Transceiver Disabled!" + return 1 + return 0 + +#undef AI_CHECK_WIRELESS +#undef AI_CHECK_RADIO diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index c9541858467..f2cd262f4c3 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -11,6 +11,7 @@ sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS see_in_dark = 8 see_invisible = SEE_INVISIBLE_LEVEL_TWO + remove_ai_verbs(src) var/callshuttle = 0 diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index f89a171e0c8..a0382f20251 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -119,7 +119,7 @@ // Return to the Core. -/mob/living/silicon/ai/verb/core() +/mob/living/silicon/ai/proc/core() set category = "AI Commands" set name = "AI Core" @@ -145,7 +145,7 @@ for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) c.remove(eyeobj) -/mob/living/silicon/ai/verb/toggle_acceleration() +/mob/living/silicon/ai/proc/toggle_acceleration() set category = "AI Commands" set name = "Toggle Camera Acceleration" diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index 9e104ac100a..e167c42f060 100755 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -1,4 +1,3 @@ - /mob/living/silicon/ai/proc/show_laws_verb() set category = "AI Commands" set name = "Show Laws" @@ -107,7 +106,7 @@ sleep(10) number++ -/mob/living/silicon/ai/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite +/mob/living/silicon/ai/proc/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite set category = "AI Commands" set name = "State Laws" diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index d0c6c767fcf..3a0c1a461c6 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -182,3 +182,7 @@ health = 100 - getOxyLoss() - getToxLoss() - getBruteLoss() else health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss() + +/mob/living/silicon/ai/rejuvenate() + ..() + add_ai_verbs(src) \ No newline at end of file diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 7a6d7140d17..2307d00bcb7 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -120,7 +120,7 @@ O.show_laws() O << "These laws may be changed by other players, or by you being the traitor." - add_ai_verbs(O) + O.add_ai_verbs() O.job = "AI" O.rename_self("ai",1) From c60a7d2e49495579febf3dc6e034f31c90a051ed Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Tue, 19 Aug 2014 21:22:06 +0200 Subject: [PATCH 2/2] Engine room tweaks. The engine cooling pump now begins online, as otherwise supermatter delamination will occur. One of the freezers now begins offline, seems power demand is just too great otherwise. --- maps/tgstation2.dmm | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/maps/tgstation2.dmm b/maps/tgstation2.dmm index 5cc9fc92ce7..f162582d963 100644 --- a/maps/tgstation2.dmm +++ b/maps/tgstation2.dmm @@ -6324,7 +6324,7 @@ "crF" = (/obj/structure/table,/obj/machinery/firealarm{dir = 2; pixel_y = 24},/obj/item/weapon/storage/box/cups{pixel_x = 0; pixel_y = 0},/turf/simulated/floor{tag = "icon-whiteblue (NORTH)"; icon_state = "whiteblue"; dir = 1},/area/medical/reception) "crG" = (/obj/structure/sign/chemistry,/turf/simulated/wall/r_wall,/area/medical/chemistry) "crH" = (/obj/machinery/atmospherics/pipe/simple/visible{dir = 4},/obj/machinery/meter{frequency = 1443; id = "engine_waste_post_filter"; name = "Engine Waste - Post-Filter"},/turf/simulated/floor/plating,/area/engine/engine_room) -"crI" = (/obj/machinery/power/smes,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 1},/area/engine/engine_room) +"crI" = (/obj/machinery/power/smes{charge = 2.5e+006},/obj/structure/cable{icon_state = "0-4"; d2 = 4},/turf/simulated/floor/plating{icon_state = "warnplate"; dir = 1},/area/engine/engine_room) "crJ" = (/obj/machinery/door/poddoor{dir = 4; id = "disvent"; name = "Incinerator Vent"},/turf/simulated/floor/engine/vacuum,/area/maintenance/incinerator) "crK" = (/obj/machinery/atmospherics/portables_connector{dir = 1},/obj/machinery/portable_atmospherics/canister/air,/turf/simulated/floor/plating,/area/storage/emergency) "crL" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating/airless,/area/rnd/test_area) @@ -10982,7 +10982,7 @@ "edj" = (/obj/structure/closet/crate/hydroponics,/obj/item/weapon/shovel/spade,/obj/item/weapon/reagent_containers/glass/bucket,/obj/item/weapon/minihoe,/obj/item/weapon/reagent_containers/spray/plantbgone{pixel_x = 13; pixel_y = 5},/obj/item/weedkiller/triclopyr,/obj/item/weapon/reagent_containers/glass/fertilizer/ez,/turf/simulated/floor/plating,/area/research_outpost/maintstore1) "edk" = (/obj/structure/table,/obj/machinery/light,/obj/item/weapon/wrench,/obj/item/device/flashlight,/obj/machinery/cell_charger,/turf/simulated/floor,/area/engine/workshop) "edl" = (/obj/machinery/atmospherics/pipe/simple/visible/yellow{dir = 4},/obj/machinery/light,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/meter,/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"},/area/engine/engine_room) -"edm" = (/obj/machinery/atmospherics/binary/pump{dir = 4; name = "Engine Filter Outpump"},/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"},/area/engine/engine_room) +"edm" = (/obj/machinery/atmospherics/unary/freezer{dir = 8; icon_state = "freezer"; req_access_txt = "56"; set_temperature = 1},/turf/simulated/floor/plating,/area/engine/engine_room) "edn" = (/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/light/small{dir = 4},/turf/simulated/floor/plating{dir = 1; icon_state = "warnplate"; nitrogen = 0.01; oxygen = 0.01},/area/engine/engine_waste) "edo" = (/obj/machinery/atmospherics/pipe/simple/visible/yellow{tag = "icon-intact (NORTHEAST)"; icon_state = "intact"; dir = 5},/obj/machinery/light,/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"},/area/engine/engine_room) "edp" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"},/area/engine/engine_room) @@ -11078,6 +11078,7 @@ "efb" = (/obj/structure/cable,/obj/machinery/power/solar{id = "construction_solar"; name = "Construction Solar Array"},/turf/simulated/floor{icon_state = "solarpanel"},/area/djstation) "efc" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/turf/simulated/floor/plating,/area/djstation) "efd" = (/obj/machinery/telecomms/relay/preset/ruskie,/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/djstation) +"efe" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0},/obj/machinery/atmospherics/binary/pump/on{dir = 4; name = "Engine Filter Outpump"},/turf/simulated/floor/plating{dir = 2; icon_state = "warnplate"},/area/engine/engine_room) (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -11271,7 +11272,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaacfWcfXcfYaaacfWcfXcfYaaacfWcfXcfYaaeaaeaaaaaaaaaaaaaaeaaeaaaaaaaaaaaacsLaaaaaabZUcdBcdEcfIcfQcfacftcdVcdOcdOcdTcdvbZDcdebZCbZCbZCccbcgtbZLbZjcVGcVGcVGcVGcVGcVGcVGaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaacmdcmdcmdcmdcmdcmdcmdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaacfWchecfYaaacfWchecfYaaacfWchecfYaaeaaeaaeaaeaaaaaacthaaaaaaaaaaaeaaaaaaaaaaaabZUcdBcdEcfZcfQcfacftcgacftcgbcgjcgncgmcgDcglcglcgZchCchgcgGbZjaaeaaeaaEaaeaaeaaeaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmdcmdcmdcmdcmdcmdcmdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaEaaecfWchecfYaaacfWchecfYaaecfWchecfYaaeaaaaaaaaeaaectyaaaaaaaaaaaaaaaaaaaaaaaaaaabZUcdBcjjcjocjQcfacftcrvcrHcjZcrmcimcgXcfocascascascjhcjdcgYbZjaaaaaaaaEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmdcmdcmdcmdcmdcmdcmdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaacfWchecfYaaecfWchecfYaaacfWchecfYaaaaaaaaaaaaaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaabZUedsedrednctkcPDbZCedqedpedoecWecVecWecTecUedledmecXecYcgYbZjaaaaaaaaEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmdcmdcmdcmdcmdcmdcmdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaacfWchecfYaaecfWchecfYaaacfWchecfYaaaaaaaaaaaaaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaabZUedsedrednctkcPDbZCedqedpedoecWecVecWecTecUedlefeecXecYedmbZjaaaaaaaaEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmdcmdcmdcmdcmdcmdcmdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaamaaEaaeaaacfWchecfYaaecfWchecfYaaacfWchecfYaaeaaaaaaaaaaaaaaeaaecjMcjNcjNcjNcjNcOXcPddgDecRecRecRecPbZjbZCbZCcPVbZjbZjbZjecMcWdecQbZjbZjbZjecScRccPSbZjaaeaaabYSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacmdcmdcmdcmdcmdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaamaaaaaeaaaaaeaaeckAaaeaaeaaeckAaaeaaaaaeckAaaeaaaaaaaaaaaaaaackBckCckDckEckFcPBcPqdhRdgEdigdicdicdihdpKbZjcOWbZCcvGcttcvEcIGecOcOLecNcIGctscttcyVbZCecLbZjaaaaaaaaEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaactvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvctvaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaEaaecltclucluclvclwclwclwclwclwclwclwclwclwclwclwclwclwclwcEZclydidcELcBvclCcwKclEdyKdyKdyKdyKdyMdyKdyNbZjbZCbZCcvGcttcvEcwIctpcyWcyXcwIctscttcyVbZCcyhbZjaaaaaaaaEaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa