From 52e2efdb7fad7c014ce3a87c04be762594bb2ed6 Mon Sep 17 00:00:00 2001 From: carnie Date: Thu, 23 May 2013 12:05:04 +0100 Subject: [PATCH] *Fixes the gaussian PRNG *Fixes a minor mistake in num2hex *Fixes a bad call to num2hex which was causing data_core records to all have an ID of "000000". Fixes #583 *Rebalances dna modification to match the PRNG fixes. *Fixes cloning computer not copying b_type to data disks DNA modifier features: *Probability indicators for emitter settings *Info on last pulse operation *Cannot operate on dead subjects *UE/UI/SE spaced out more Modified code/__HELPERS/maths.dm Modified code/__HELPERS/type2type.dm Modified code/__HELPERS/unsorted.dm Modified code/datums/datacore.dm Modified code/game/dna.dm Modified code/game/machinery/computer/cloning.dm Modified code/game/machinery/computer/security.dm --- code/__HELPERS/maths.dm | 9 ++- code/__HELPERS/type2type.dm | 3 +- code/__HELPERS/unsorted.dm | 12 +--- code/datums/datacore.dm | 2 +- code/game/dna.dm | 73 +++++++++++++++--------- code/game/machinery/computer/cloning.dm | 1 + code/game/machinery/computer/security.dm | 2 +- 7 files changed, 59 insertions(+), 43 deletions(-) diff --git a/code/__HELPERS/maths.dm b/code/__HELPERS/maths.dm index fc5ad930680..8357be648df 100644 --- a/code/__HELPERS/maths.dm +++ b/code/__HELPERS/maths.dm @@ -114,6 +114,9 @@ var/const/Sqrt2 = 1.41421356 //since this method produces two random numbers, one is saved for subsequent calls //(making the cost negligble for every second call) //This will return +/- decimals, situated about mean with standard deviation stddev +//68% chance that the number is within 1stddev +//95% chance that the number is within 2stddev +//98% chance that the number is within 3stddev...etc var/gaussian_next #define ACCURACY 10000 /proc/gaussian(mean, stddev) @@ -126,9 +129,9 @@ var/gaussian_next R1 = rand(-ACCURACY,ACCURACY)/ACCURACY R2 = rand(-ACCURACY,ACCURACY)/ACCURACY working = R1*R1 + R2*R2 - while(working >= 1) + while(working >= 1 || working==0) + working = sqrt(-2 * log(working) / working) R1 *= working - R2 *= working - gaussian_next = R2 + gaussian_next = R2 * working return (mean + stddev * R1) #undef ACCURACY \ No newline at end of file diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 8ce304f3338..c7045f207c1 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -38,6 +38,7 @@ //if len < 0 then the returned string will be as long as it needs to be to contain the data //Only supports positive numbers //if an invalid number is provided, it assumes num==0 +//Note, unlike previous versions, this one works from low to high <-- that way /proc/num2hex(num, len=2) if(!isnum(num)) num = 0 @@ -45,7 +46,7 @@ . = "" var/i=0 while(1) - if(len<0) + if(len<=0) if(!num) break else if(i>=len) break diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index a7c982e108b..09b375967d3 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -20,15 +20,9 @@ var/r = hex2num(textr) var/g = hex2num(textg) var/b = hex2num(textb) - textr = num2hex(255 - r) - textg = num2hex(255 - g) - textb = num2hex(255 - b) - if (length(textr) < 2) - textr = text("0[]", textr) - if (length(textg) < 2) - textr = text("0[]", textg) - if (length(textb) < 2) - textr = text("0[]", textb) + textr = num2hex(255 - r, 2) + textg = num2hex(255 - g, 2) + textb = num2hex(255 - b, 2) return text("#[][][]", textr, textg, textb) return diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 347474f39d5..1e52ae098db 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -30,7 +30,7 @@ else assignment = "Unassigned" - var/id = add_zero(num2hex(rand(1, 1.6777215E7)), 6) //this was the best they could come up with? A large random number? *sigh* + var/id = num2hex(rand(1, 1.6777215E7),6) //this was the best they could come up with? A large random number? *sigh* //General Record var/datum/data/record/G = new() diff --git a/code/game/dna.dm b/code/game/dna.dm index 37d64002669..043c8a20032 100644 --- a/code/game/dna.dm +++ b/code/game/dna.dm @@ -4,12 +4,10 @@ #define NUMBER_OF_BUFFERS 3 #define RADIATION_STRENGTH_MAX 15 -#define RADIATION_STRENGTH_MULTIPLIER 5 //larger has a more range -#define RADIATION_STRENGTH_BIAS 0 //skews the randomisation based on radstrength*num +#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has a more range #define RADIATION_DURATION_MAX 30 -#define RADIATION_ACCURACY_MULTIPLIER 12 //larger is less accurate -#define RADIATION_ACCURACY_BIAS 0 //skews the randomisation based on radduration*num +#define RADIATION_ACCURACY_MULTIPLIER 4 //larger is less accurate #define RADIATION_IRRADIATION_MULTIPLIER 0.3 //multiplier for how much radiation a test subject recieves @@ -140,26 +138,21 @@ /proc/getblock(input, blocknumber, blocksize=DNA_BLOCK_SIZE) return copytext(input, blocksize*(blocknumber-1)+1, (blocksize*blocknumber)+1) -/* -/proc/getblockbuffer(input,blocknumber,blocksize) - var/result[blocksize] - var/start = (blocksize*blocknumber)-blocksize - for(var/i=1, i<=blocksize, i++) - result[i] = copytext(input, start+i, start+i+1) - return result -*/ + /proc/setblock(istring, blocknumber, replacement, blocksize=DNA_BLOCK_SIZE) if(!istring || !blocknumber || !replacement || !blocksize) return 0 return getleftblocks(istring, blocknumber, blocksize) + replacement + getrightblocks(istring, blocknumber, blocksize) /proc/scramble(input,rs,rd) var/length = length(input) - var/num = hex2num(input) - num = round(num + gaussian(rs*RADIATION_STRENGTH_BIAS, rs*RADIATION_STRENGTH_MULTIPLIER), 1) - return num2hex(Wrap(num, 0, 16**length), length) + var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER) + if(ran == 0) ran = pick(-1,1) //hacky, statistically should almost never happen. 0-change makes people mad though + else if(ran < 0) ran = round(ran) //negative, so floor it + else ran = -round(-ran) //positive, so ceiling it + return num2hex(Wrap(hex2num(input)+ran, 0, 16**length), length) /proc/randomize_radiation_accuracy(position_we_were_supposed_to_hit, radduration, number_of_blocks) - return Wrap(round(position_we_were_supposed_to_hit + gaussian(radduration*RADIATION_ACCURACY_BIAS, RADIATION_ACCURACY_MULTIPLIER/radduration), 1), 1, number_of_blocks+1) + return Wrap(round(position_we_were_supposed_to_hit + gaussian(0, RADIATION_ACCURACY_MULTIPLIER/radduration), 1), 1, number_of_blocks+1) /proc/randmutb(mob/living/carbon/M) if(!check_dna_integrity(M)) return @@ -710,7 +703,7 @@ return /obj/machinery/computer/scan_consolenew/attackby(obj/item/W as obj, mob/user as mob) - if((istype(W, /obj/item/weapon/disk/data)) && (!diskette)) + if(istype(W, /obj/item/weapon/disk/data) && !diskette) user.drop_item() W.loc = src diskette = W @@ -728,9 +721,9 @@ return ShowInterface(user) -/obj/machinery/computer/scan_consolenew/proc/ShowInterface(mob/user) +/obj/machinery/computer/scan_consolenew/proc/ShowInterface(mob/user, last_change) if(!user) return - var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 880, 450) // Set up the popup browser window + var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 880, 470) // Set up the popup browser window popup.add_stylesheet("scannernew", 'html/browser/scannernew.css') var/mob/living/carbon/viable_occupant @@ -744,12 +737,13 @@ switch(viable_occupant.stat) if(CONSCIOUS) occupant_status = "Conscious" if(UNCONSCIOUS) occupant_status = "Unconscious" - else occupant_status = "DEAD" + else occupant_status = "DEAD - Cannot Operate" occupant_status = "[viable_occupant.name] => [occupant_status]
" occupant_status += "
Health:
[viable_occupant.health]%
" occupant_status += "
Radiation Level:
[viable_occupant.radiation]%
" var/rejuvenators = viable_occupant.reagents.get_reagent_amount("inaprovaline") occupant_status += "
Rejuvenators:
[rejuvenators] units
" + occupant_status += "
Last Operation:
[last_change]
" else viable_occupant = null occupant_status = "Invalid DNA structure" @@ -763,7 +757,18 @@ else occupant_status = "Error: Undefined" scanner_status = "Error: No scanner detected" - var/status = "
Scanner Status: [scanner_status]
Subject Status: [occupant_status]
Emitter Array Output Level: [radstrength]
Emitter Array Pulse Duration: [radduration]
" + + var/status = "
Scanner Status: [scanner_status]
Subject Status: [occupant_status]
" + var/stddev = radstrength*RADIATION_STRENGTH_MULTIPLIER + status += "Emitter Array Output Level: [radstrength] Mutation: (-[stddev]<->+[stddev])=68% (-[2*stddev]<->+[2*stddev])=95%
" + stddev = RADIATION_ACCURACY_MULTIPLIER/radduration + var/chance_to_hit + switch(stddev) //hardcoded values from a z-table for a normal distribution + if(0 to 0.25) chance_to_hit = ">95%" + if(0.25 to 0.5) chance_to_hit = "68-95%" + if(0.5 to 0.75) chance_to_hit = "55-68%" + else chance_to_hit = "<38%" + status += "Emitter Array Pulse Duration: [radduration] Accuracy: ([chance_to_hit])
" var/buttons = "Scan " if(connected) buttons += "Toggle Bolts " @@ -846,15 +851,16 @@ temp_html += status temp_html += buttons + var/max_line_len = 10*DNA_BLOCK_SIZE + temp_html += "
Unique Enzymes :
" if(viable_occupant) temp_html += "[viable_occupant.dna.unique_enzymes]" else temp_html += " - " - temp_html += "
" + temp_html += "
" temp_html += "
Unique Identifier:
" - var/max_line_len = DNA_BLOCK_SIZE * 10 if(viable_occupant) var/len = length(viable_occupant.dna.uni_identity) for(var/i=1, i<=len, i++) @@ -865,7 +871,7 @@ temp_html += " " else temp_html += " - " - temp_html += "
" + temp_html += "
" temp_html += "
Structural Enzymes:
" if(viable_occupant) @@ -905,6 +911,7 @@ //Basic Tasks/////////////////////////////////////////// var/num = round(text2num(href_list["num"])) + var/last_change switch(href_list["task"]) if("togglelock") if(connected) connected.locked = !connected.locked @@ -1010,7 +1017,7 @@ diskette.loc = get_turf(src) diskette = null if("pulseui","pulsese") - if(num && viable_occupant && connected) + if(num && viable_occupant && connected && viable_occupant.stat != DEAD) radduration = Wrap(radduration, 1, RADIATION_DURATION_MAX+1) radstrength = Wrap(radstrength, 1, RADIATION_STRENGTH_MAX+1) @@ -1031,8 +1038,14 @@ num = Wrap(num, 1, len+1) num = randomize_radiation_accuracy(num, radduration, len) + var/block = round((num-1)/DNA_BLOCK_SIZE)+1 + var/subblock = num - block*DNA_BLOCK_SIZE + last_change = "UI #[block]-[subblock]; " + var/hex = copytext(viable_occupant.dna.uni_identity, num, num+1) + last_change += "[hex]" hex = scramble(hex, radstrength, radduration) + last_change += "->[hex]" viable_occupant.dna.uni_identity = copytext(viable_occupant.dna.uni_identity, 1, num) + hex + copytext(viable_occupant.dna.uni_identity, num+1, 0) updateappearance(viable_occupant) @@ -1041,8 +1054,14 @@ num = Wrap(num, 1, len+1) num = randomize_radiation_accuracy(num, radduration, len) + var/block = round((num-1)/DNA_BLOCK_SIZE)+1 + var/subblock = num - block*DNA_BLOCK_SIZE + last_change = "SE #[block]-[subblock]; " + var/hex = copytext(viable_occupant.dna.struc_enzymes, num, num+1) + last_change += "[hex]" hex = scramble(hex, radstrength, radduration) + last_change += "->[hex]" viable_occupant.dna.struc_enzymes = copytext(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext(viable_occupant.dna.struc_enzymes, num+1, 0) domutcheck(viable_occupant, connected) @@ -1052,7 +1071,7 @@ if(connected) connected.locked = locked_state - ShowInterface(usr) + ShowInterface(usr,last_change) /////////////////////////// DNA MACHINES @@ -1063,11 +1082,9 @@ #undef RADIATION_STRENGTH_MAX #undef RADIATION_STRENGTH_MULTIPLIER -#undef RADIATION_STRENGTH_BIAS #undef RADIATION_DURATION_MAX #undef RADIATION_ACCURACY_MULTIPLIER -#undef RADIATION_ACCURACY_BIAS #undef RADIATION_IRRADIATION_MULTIPLIER diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index da99eb150ea..b32a3cc7fe5 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -351,6 +351,7 @@ R.fields["UE"] = subject.dna.unique_enzymes R.fields["UI"] = subject.dna.uni_identity R.fields["SE"] = subject.dna.struc_enzymes + R.fields["b_type"] = subject.dna.b_type //Add an implant if needed var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject) diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 555e04e5f73..e53662a89ac 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -389,7 +389,7 @@ What a mess.*/ if ("New Record (General)") var/datum/data/record/G = new /datum/data/record() G.fields["name"] = "New Record" - G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6)) + G.fields["id"] = "[num2hex(rand(1, 1.6777215E7), 6)]" G.fields["rank"] = "Unassigned" G.fields["sex"] = "Male" G.fields["age"] = "Unknown"