Katie
From MW4:Wiki
for
Katie
Jump to:
navigation
,
search
== Introduction == Katie (Killer ABL scripT with Interoperable Enigmas) was supposed to be the super-sexy, panty-wettingly state machine which would handle the salvage of all mechs you kill. Instead, it's gonna be a little independent, selfcontained system engine for handling the complete salvage of mechs. It will be extremely easy and straightforward to use, as simple as calling katie(mechHandle), and yet powerful enough to decide and randomize everything for you - wheather the mech is going to be salvaged normally, damaged or crippled AS WELL as some of it's weapons - is completely contained within Katie so you don't have to worry about a thing.. Katie's code is quite long, so I'll comment the parts first and post the code later. Since I'm testing as I'm developing, Katie is sure to work... eventually. I'll be adding on piece by piece until it's a complete salvage handling engine. To be completely honest, I don't know if I should make it modular or not. Modularity might increase the number of eternals required for the modules to communicate, while making it non-modular will decrease comprehensibility. Still, since it's purpose-build, there's really no reason to break it up. So far. <ref>[http://mektek-dynamicsalvage.wikispaces.com/Katie#Discussion Explanation of the dynamic salvage scripting written by RkShaRkz on the mektek-dynamicsalvage wiki site]</ref> *UPDATE* You can view full Katie's code in your Content\ABLScripts\Katie folder. You'll find two files - the meat and the constants. ===The constants=== An essential part of Katie are the constants. Yes, i've spent some time writing them, and most of the mech strings are unchecked but that's just fine. It's a work in progress, and those can easily be fixed. What *is* important is that every mech has a placeholder string now. So, it's just a matter of cross-checking the defined ones against the real working ones and we're all done. The constants are divided up into four parts: ===MechIDs=== These are self-explanatory, they hold the IDs of all mechs found in the mechlab_something_headers.h ===MechStrings=== These hold the string literals belonging to each ID. The mapping, however, is done in a rather shady way, such that there is no "visible" connection between the two. There is a function (well, a part of the code) that translates a MechID -> MechString and assigns that string to a variable. The same part of the code handles Variant translation as well, but I'll get back to that later. So you see, once you get the string in the variable, we cannot use it to obtain the ID back, but we don't really need to because of two reasons: :* You aren't gonna meddle in this code anyway so it's really of no concern to the end user :* We still have it in the iMechID variable One more thing that should be noted is that only the first 44 (microsoft) mechs have valid strings. The others just use placeholders for now, but that's just minor legwork to "fix" and adapt. ===WeaponIDs=== Similar to MechIDs, these are self-explanatory as well. The reason these are used tho, is because of the Variant encoding i'll mention later down. ===WeaponStrings=== These hold the string literals belonging to each weapon ID. The mapping is the same as with mechs, that is - a piece of code is there to map the strings to integers and store them. Unlike MechStrings, these all work. ===Miscellanious Constants=== Well, I needed two really, but i have three for my reasons. The first one is CRIPPLED_CHANCE which is set to 50. This defines the chances of the mechs being salvaged as crippled, so half of the mechs you get should be crippled. NORMAL_CHANCE which is set to 20. This means that roughly 20% of all mechs you get should be salvaged as normal. Note: These chances are in addition to those passed to katie as the base salvage chance. Unlike the "setKillSalvageChance", Katie can still work out something even if we don't salvage the mech. But it needs to be dead if there's anything to be done to it. In other words, calling katie on "living" mechs will yield nothing, as well as calling it on non-mech targets. SEPARATOR_WEAPON used in the decoding process (well, encoding too but those are done by hand) during variant processing. NO_HASH used when a given variant hash isn't long enough to fill in all the hash-parts. ===Variant Constants=== This is the interesting part. I've noted all stock variants of all mechs and encoded them by hand. Because of the 7-digit bug, I had to break up the hashes. Here's a human-readable list of all the stocks currently in MP3.02b <pre> core ArcticWolf - 4CSTRK6 (1) Argus - LRM10 2MDLAS 2ULTRA5 MG (4) Atlas - 2LRM15 2SMLAS 2PPC Gauss (4) Awesome - 3PPC 2MDLAs SRM4 (3) BlackKnight - MDLAS 2LGLAS 2PPC (3) Bushwacker - LRM10 LRM5 AC10 2MDPLS (4) Catapult - 2ALRM20 2MDLAS LGLAS (3) CauldronBorn - 2CLRM15 2CLBX10 2CERMDL (3) Chimera - MG MRM20 LGLAS MDLAS (4) Cougar - 2CLRM10 2CERMDL CERLGL (3) Daishi - CLRM20 2CULTR5 4CERLGL (3) Dragon - MDLAS LRM10 AC5 HGauss (4) Fafnir - 2HGauss 2LGLAS 3MDLAS (3) Flea - 2SMLAS 2MG Flamer (3) Gladiator - CERPPC CULTR20 CERLGL 2CERMDL 2CHSML (5) Hauptmann - LBX20 LRM15 4SMLAS 2LGLAS 2MDPLS (5) Hellhound - 2CERLGL CSTRK6 CLBX10 (3) Hellspawn - 2SRM6 3MDPLS (2) Highlander - Gauss HGauss 2LGLAS (3) Hunchback - LBX20 2MDLAS SRM6 (3) Kodiak - CLBX20 2CSMRM40 4CERMDL (3) Loki - CSTRK6 2CLBX10 4CERMDL (3) Longbow - 2LRM20 2LRM15 3MDLAS (3) MadCat - 2CLRM20 2CMDPLS 2CMG 2CERLGL (4) MadCat_MKII - 2CLRM10 2CGauss 4CERMDL (3) Masakari - CULTR5 CLRM15 CLRM20 2CERPPC (4) Mauler - 2LRM10 4ULTRA2 4MDLAS (3) NovaCat - 2CERPPC 3CERLGL (2) Osiris - MH 5MDLAS SRM6 (3) Owens - 2MDLAS 2LRM15 (2) Puma - 2CERPPC (1) Raven - LRM15 NARC SMLAS 2SMPLS (4) Ryoken - 2CLRM15 2CERLGL 2CERMDL (3) ShadowCat - 3CERMDL CERLGL CMG CSTRK (4) Sunder - 4LGLAS 2MDLAS LBX20 (3) Templar - 2LGauss 2LGXPLS (2) Thanatos - 3MDPLS MRM20 LBX20 (3) Thor - CLRM15 4CERMDL 2CULTR5 (3) Uller - 2CLRM10 CERMDL CERLGL (3) Uziel - 2PPC 2MG SRM6 Flamer (4) Victor - HGauss Gauss 2MDPLS SRM4 (4) Vulture - 2CLRM20 4CMDPLS (2) Wolfhound - LGXPLS 2MDPLS (2) Zeus - HGauss 2LRM15 2MDPLS LGLAS (4) mp1 Avatar - SMLAS 2MDLAS 2MDPLS LAC5 LBX10 LRM15 (6) !!! Warhammer - SRM6 2MG 2MDXPLS 2PPC (4) Strider - 2SRM6 3MDLAS 3SMLAS (3) Marauder - ULTRA5 SMPLS 2PPC 3MDPLS (4) BloodAsp - 2CGauss 4CHMDL CSTRK6 (3) Ares - 4LMG ATM12M 2CSMPLS CMDPLS CHLGL CHMDL (6) !!! Stalker - 2HRL 2RL20 4MDLAS HVAC20 (4) UrbanMechIIC - 2LMG CLBX10 CHMDL (3) UrbanMech - 3MDLAS MG SMLAS RAC5 (4) mp2 Warthog - 2ATM6E 4CHMDL 2CLBX20 (3) Annihilator - 4LBX10 2MG 2MDLAS (3) BlackLanner - 2ATM6M CERLGL 2CHMDL (3) Commando - LGLAS MDLAS 2SMLAS RL20 (4) Canis - 2CULTR10 2CERLGL 2CERMDL (3) Dasher - 2CERMDL 2CSTRK2 (2) BlackHawk - 12CERMDL (1) (*) Solitaire - CHLGL 2CHSML 2CHMDL (3) Rifleman - 2LGLAS 2MDPLS 2AC5 (3) Brigand - 2MG 2MDLAS 2MDPLS SMLAS (4) Hollander2 - Gauss 3MDLAS 3SMLAS (3) Grizzly - 2CLRM15 CERLGL CGauss CHLGL (4) GrimReaper - 2RL20 3LGLAS 2SMXPLS (3) ArgusXT - LBX20 ULTRA5 2MDLAS 2SMLAS (4) ThanatosXT - RAC2 4SMLAS LBX10 LBX20 (4) Cyclops - ASLTLAS HGauss Gauss RL20 LRM15 2MDLAS (6) !!! Gargoyle - HMG CERSML 2CLBX5 CSTRK6 CERLGL (5) Gesu - 2CLRM15 2HMG 2CERLGL (3) Deimos - 2CLRM15 6CULTR2 2CERMDL (3) mp3 Tenchi - 4MDLAS 2RAC2 2MG (3) Crab - 2LGLAS LGPLS MDPLS (3) Orion2c - 2LTPPC CGauss CERLGL ATM12M HMG (5) Jenner2c - 2CSTRK6 CSTRK4 2CERMDL (3) Behemoth - 2CGauss 2CLGPLS CSMPLS (3) Battlemaster - 2RAC2 2MDLAS PPC CapPPC SRM6 (5) Archer - 2LRM20 4MDLAS LGLAS (3) Locust2c - CHMDL 3CHSML 2CSTRK2 (3) Wasp - 2MDLAS SMLAS (2) Telos - 2RAC2 2RAC5 2RL20 (3) Vulture2 - CHMDL 2CLRM15 2CERSML CERPPC HMG CLBX20 (6) !!! Supernova - 6CERLGL (1) (*) Thug - 2SRM6 2PPC 2MDLAS (3) Reaver - 2CHLGL 2CHSML (2) Wildcat - 2CRAC20 4CERMDL 2CHMDL (3) Razorback - LGLAS 2MDLAs SMLAS SRM4 2MG (5) ShadowHawk - 4MDXPLS SRM6 RAC5 (3) /* elemental, longinus, kanazuchi */ Koto - LGXPLS SMLAS 2MG (3) DuanGung - 2MDLAS 2SMLAS ALRM10 (3) BlackJack2 - LGLAS LAC2 SRM4 PPC (4) /* golem, standard, gnome */ Katapult - 2PPC 2LGLAS (2) Hunchback2c - 2CLBX20 2CERMDL (2) Behemoth2 - 4CERLGL CRAILGUN (2) Warlord - 3MDLAS 2LGLAS ALRM20 LBX20 RAC5 (5) /* CinfB-E-M, ISinfB-E-M */ Ursus - CERLGL 4CMDPLS CSTRK6 CLRM10 (4) /* salamander, greydeath, infiltrator */ VultureC - 2CGauss 2CERSML CERMDL (3) Fenris - CSTRK6 CERLGL CERSML CERPPC CSTRK4 (5) Privateer - 4MG 2SRM2 LGLAS MDLAS HRL (5) RabidCoyote - 4CMDPLS ATM12M (2) Yeoman - 2LRM15 2LRM10 2MDPLS LGLAS (4) Pitbull - 2CHMDL 2LTPPC 2HMG CLBX20 (4) Panther - PPC SRM4 SMPLS (3) Trebuchet - LRM15 SRM6 3MDLAS (2) BlackHeart - 2LGauss SRM6 2SRM4 2MDLAS (4) Battlemaster2c - 2LTPPC 2CULTR5 LCPPC CSTRK6 (4) Assassin2 - ALRM10 2SRM4 4MDPLS (3) Centurion - 2MDPLS 2MDLAS LRM10 AC20 (4) Marauder2 - 2PPC LGPLS 2MDLAS 2SMPLS 2LMG Gauss (6) !!! Bowman - 3CHMDL 3LMG 2ArrowT (3) </pre> The mechs marked with (*) are exceptions and had to be handled a bit differently. Thankfully, being a human that I am, I managed to trick my code into accepting the weirdy variants. More word on them later, or for mental excercise - try coding/decoding them yourself ;) == Coding / Decoding algorithms == This section will describe the coding/decoding algorithms used in Katie. Don't know why really since this is also of no concern to the end-user, but I guess i should document it well AND appease your thirst for scripting tricks. So, without further adieu, here are the coding algorithms. ===Coding Algorithm=== Since I *haven't* decided on the algorithm yet, I will just explain both and in the end one of these will most probably be picked unless they both get rejected because of the sample data. The coding will be done by hand, because :* it's easier :* I don't want to spend time debugging/fixing something that has to be an outside project anyway :* all I need to do it is a calculator and that's it. If you're going to say "Yes, but how is that manageable" I will respond to that easily - it isn't. It's not made to be manageable since there SHOULD be no management. The constant tables are as is, and all i need to do is leave a comment (a formula) by which i've encoded those so that anyone that wants to add to it can do it. Because of the 7 digit bug, I've decided to go with the following coding algorithm ===Variation A:=== This algorithm encodes the stock variant using a following method //the following is of course the pseudo code illustrating the method. <pre>/* The following example will demonstrate how to encode the Awesome's stock consisting of [PPC, PPC, PPC, SRM6, SRM4] */ 1) translate the stock list into a list of unique weapon pairs. so our list transforms into [(PPC, 3), (SRM6, 1), (SRM4, 1)] 2) set the padding to 1 3) for every weapon type in the transformed list do hash += (MAXIMUM_WEAPON_ID * (quantity-1) + CURRENT_WEAPON_ID) * padding; pading *= 1000; which means that after processing the first weapon of the list - PPC, our hash code will look something like this (in steps, with the dashed lines being the initial conditions) Step 1: -hash = 0; -MAXIMUM_WEAPON_ID = 135; -quantity = 3; -CURRENT_WEAPON_ID = 15; //PPC hash = 0 + (270 + 15) * 1 = 285. //the reason we store with quantity-1 is that if the quantity is less than one, the weapon will not appear in the list at all, so we conserve space and buy an additional "space" Step2: - hash = 285; - CURRENT_WEAPON_ID = 69; //srm6 - quantity = 1; - padding = 1,000; hash = 285 + (0*135 + 69) * 1000 = 69,285; //it's important to use three digits per weapon. Step3: - hash = 069285; (note the leading zero here!) - CURRENT_WEAPON_ID = 68; //srm4 - quantity = 1; - padding = 1,000,000; hash = 69285 + (0*135 + 68) * 1 000 000 = 68,069,285; This example illustrates the power and vulnerabilities of this algorithm. The pros are: - only three digits per weapon type - counting the integer constraints in ABL which are 20 digits, this can be used to encode 6 weapon types. The cons are: - with the current MAXIMUM_WEAPON_ID of 135, this algorithm can "save" up to 7 weapons of certain type. (6*135 = 600 + 180 + 30 = 810; 810 + 134 = 944) - the MAXIMUM_WEAPON_ID will increase, and if it increases by more than 5, this algorithm's efficiency drops. The bottomline is - IT MUST NEVER OVERFLOW a 1000, or in other words, the value for each weapon must never be higher than 999. We repeat that for every hash part we have. Hash parts usually consist of two weapon types. </pre> This means that with four parts that I am using, I could easily encode eight different weapon types, with up to 6 weapons in every one of them. If there are more than 6 weapons of a given type, I'll just encode it as a different weapon type. The algorithm won't mind and I won't have to smash my head to think of an exception handler. Plus - I can afford it :) == Pseudo-code == On a second thought - I'm gonna leave the pseudo code here instead. It illustrates how Katie works just fine. <pre> function Katie(ObjectID mechHandle, int chance); vars char [30] strMech; char [30,30] strWeapons; integer [30] iWeaponIDs; integer [30] iWeaponChances; integer iNum, iMechID, iMechVariant, iPicks, iWeaponSize; code if(isMech(mechHandle) and isDead(mechHandle)) then (iMechID, iMechVariant) <- recognize mechHandle strMech <- translate iMechID; iNum = Rand(1,100); if(num <= chance) then //salvage iNum = Rand(1,100); if(iNum > CRIPPLED_CHANCE) then //num > 50 AddMechInstanceSalvageCrippled(strMech); else //num <=50 if(iNum > NORMAL_CHANCE) then //num > 20 AddMechInstanceSalvageDamaged(strMech); iWeaponChances[iPicks] = iNum; //save the chance iPicks = iPicks + 1; else //num <= 20 AddMechInstanceSalvage(strMech); iWeaponChances[iPicks] = 100 - iNum; iPicks = iPicks + 1; iWeaponChances[iPicks] = 70 - iNum; iPicks = iPicks + 1; endif; // num > NORMAL endif; //num > CRIPPLE iWeaponChances[iPicks] = Rand(1,100); iPicks = iPicks + 1; else //no salvage iWeaponChances[iPicks] = iNum; //num > chance so it's good enough for salvaging a weapon iPicks = iPicks + 1; endif; // salvage /* weapon stuff now */ (iWeaponIDs, iWeaponSize) <- decode variant iMechVariant strWeapons <- translate iWeaponIDs if(iPicks >= iWeaponSize) then iPicks = iWeaponSize; //we can't salvage more than the mech has endif; for i=0 to (iPicks-1) do //will do for all picks iNum = Rand(1,100); if(iNum <= iWeaponChances[i]) then repeat iNum = Rand(0, iWeaponSize); until(not (iWeaponIDs[iNum] == -1)); //fixed the semicolon bug. //now we can salvage and be sure we have picked a unique part AddWeaponSalvage(strWeapons[iNum], 1); iWeaponIDs[iNum] = -1; endif; //salvage gun endfor; endif; //not mech or not dead endfunction; </pre> A beauty, eh? ;) == So How Does it All Work? == In any case, here's a translation for the less code-literate people. 1) We check if the mechHandle is a dead mech 2) If not, we go to #11, else we proceed to #3. 3) We recognize and store the mechID and it's stock variant. 4) Now we roll a die and compare it to our salvage chance that was passed to the function 5) If it's less that means we get to salvage and proceed to #6, else we proceed to #11. 6) Now we roll another die to see the condition of the salvaged mech against a set of hardcoded chances and proceed to steps #6.1, #6.2 or #6.3. 6.1) If it's more than 50, we salvaged a crippled mech and get no additional weapons from it. 6.2) If it's between 20 and 50, we salvaged a damaged mech and get a slim shot of getting a single additional weapon from it. 6.3) If it's less than 20 we salvage a normal mech and get two good shots at obtaining additional weapons from it.. 7) Randomly determine the chances for getting another weapon from the scrap. Proceed to #9. 8) We get a good chance of obtaining just a weapon of the destroyed mech that's beyond salvage. 9) We decode and store the mech's weapons, and perform a safety check. 10) For every "chance to obtain a weapon" we got, we do the following 10.1) Roll a die 10.2) If it's less than the associated chance, we get to salvage and proceed to #10.2.1, else we go to #10 10.2.1) Now we make sure that we pick a weapon we haven't picked before 10.2.2) salvage it and mark it as "already picked", and proceed to #10 11) End. So, now you know what it does. And here's the good part - it takes 1500 lines of code to make it work flawlessly. That's approximately 150 times more than the algorithm described above, and probably 10 times more than the pseudocode described even if most of it looks working (and most of it IS working code) '''That's all folks, good bye and thanks for all the fish.''' == References == <references/> [[Category:Single Player Campaign Guides]]
Return to
Katie
.
Views
Page
Discussion
View source
History
Personal tools
216.73.216.143
Talk for this IP address
Log in
Navigation
Main page
Community portal
Current events
Recent changes
Random page
Help
Search
Toolbox
What links here
Related changes
Special pages