ID:149376
 
Hey, I'm making a game and within it, I'd like each item to have 3 states:
Unidentified
Partially Identified
Identified

I'd like to impliment these in a form so that the player has a chance of ID'ing them depending on his/her perception in the following fashion:

IDChance = Perception^2 / Value of item in Gold

for partial ID'ing. and full ID would be:
IDChance = Perception^2 / Value in Gold * ItemModifier

and it would check to see if IDChance > 1, ie it would have to be at least 1.00 for you to properly ID the item (I want it to be very difficult).

Otherwise you can pay the Seer an amount for ID'ing as well, which works 100% of the time.

The problem I have is figuring out how to make it so that you see this reflected on the stat panel with each individual item, allow it to be ID'd by the Seer, and also reflect it in every other case I can't think of right now.

I was thinking of using vars to represent the states, but then how do you reflect changes on the stat panel, alter ID states, and perceptions when you get & drop them. And how do you make it so each character's ID is individual ( unless it's sold ), but still allow it to be saved and remember how far along it is when you load the item?
ShadowWolf wrote:
The problem I have is figuring out how to make it so that you see this reflected on the stat panel with each individual item, allow it to be ID'd by the Seer, and also reflect it in every other case I can't think of right now.

The statpanel will display the icon, name, and suffix of atoms displayed. If those three vars don't suit your needs, you can always add an extra text line.

I was thinking of using vars to represent the states, but then how do you reflect changes on the stat panel, alter ID states, and perceptions when you get & drop them. And how do you make it so each character's ID is individual ( unless it's sold ), but still allow it to be saved and remember how far along it is when you load the item?

An assosiative list would be the best way to store ID values for a number of different individuals. Since the mobs will change as players disonnect and reconnect to the game, you'll want to index the list by something that will always be the same. Probably the client key and character name. In the stat proc, you can display it like so:

obj
var
list/IDpercent = list() // list of identification percentages indexed by mob.key + mob.name

mob/Stat()
if(statpanel("Inventory"))
for(var/obj/O in contents)
stat(O) // display the obj
stat("[O.IDpercent[key + name]]% identified") // display the IDpercent for this mob

If you want it all on one line, and don't mind the ID% preceeding the item, you could replace the two stat() lines with:

stat("[O.IDpercent[key + name]]%", O)

ShadowWolf wrote:
Hey, I'm making a game and within it, I'd like each item to have 3 states:
Unidentified
Partially Identified
Identified

This smells like a Roguelike to me, and I'm darn proud to see someone making one.

The problem I have is figuring out how to make it so that you see this reflected on the stat panel with each individual item, allow it to be ID'd by the Seer, and also reflect it in every other case I can't think of right now.

To get this to display correctly in the user's stat panel, you need to change its name var. However, you have to be careful to reset the name when the object is dropped, and never to show it in the stat panel of another user. (Also you have to watch out for input() and be careful with that, if for example you use it for a thief stealing from someone else.)

For objects on the ground things get a little trickier. When you mouse over an object or list it, you'd probably like to see it reflect its known, identified name, not its general name. Seeing "potion of healing" is a lot more meaningful than "orange potion". Likewise anywhere you'd view this in a list you'd want to see its IDed name.

If you want to get fancy and work around the mouseover problem, you might need to override some of the mouse procs. I'm not sure what kind of success you'd have with that, but the whole thing would be a mess.

I was thinking of using vars to represent the states, but then how do you reflect changes on the stat panel, alter ID states, and perceptions when you get & drop them. And how do you make it so each character's ID is individual ( unless it's sold ), but still allow it to be saved and remember how far along it is when you load the item?

This you can accomplish with an associative list:
mob
var/list/IDed
var/list/discovered

proc/IDlevel(atom/movable/A)
var/l=0
if(IDed) // if list exists
l=IDed[A]
if(!l) l=0
if(discovered)
var/d=discovered[A.type]
if(d) l|=d
return l

Now, I'm not sure how this system is affected by saving and loading the world; it might be that object references won't stay intact, but others would know more about this than I would.

Anyway, the system works like this: Each mob knows which objects it has identified, and which types of objects it can identify on sight. Thus, even if you haven't identified a specific runed spear, it might be recognized as an elven spear if you know what to look for. I used the OR operator | because you may want to use bitwise flags for this system:
var/const/IDENT_TYPE=1
var/const/IDENT_PLUS=2 // +3 sword, -2 shield, 5 charges in wand...
var/const/IDENT_BLESSING=4 // blessed, cursed?
var/const/IDENT_SPECIAL=8 // rustproof, fireproof...
var/const/IDENT_ALL=255

Then when you went to build a more specific name for the object, you could do it thus:
atom/movable
var/blessed
var/plus
var/iscountable=0 // used for counted items
var/special

proc/SpecificName(idlevel)
return name

proc/macroA(word,plural=0)
if(iscountable && plus>1) return "[plus] [word]"
if(plural) return "some [word]"
var/letter=copytext(ckey(word),1,2)
if(findtext("aeiou",letter) || \
(letter=="y" && !findtext("aeiou",copytext(ckey(word),2,3))))
return "an [word]"
return "a [word]"

obj/item/weapon
var/genericname
var/specificname
var/ismetal

SpecificName(idlevel)
var/t=""
if(idlevel && IDENT_BLESSING)
if(!blessed) t="uncursed "
else if(blessed>0) t="blessed "
else t="cursed "
if(idlevel && IDENT_SPECIAL) t+="[ismetal?"rust":"fire"]proof "
if(idlevel && IDENT_PLUS) t+="[(plus>=0)?"+":""][plus] "
t+=(idlevel && IDENT_TYPE)?specificname:genericname
return macroA(t)

obj/item/potion
var/genericname // a ___ potion
var/specificname // a potion of ___
iscountable=1

SpecificName(idlevel)
var/t=""
if(idlevel && IDENT_BLESSING)
if(!blessed) t="uncursed "
else if(blessed>0) t="blessed "
else t="cursed "
var/s=(plus>1)?"s":""
t+=(idlevel && IDENT_TYPE)?"potion[s] of [specificname]":"[genericname] potion[s]"
return macroA(t)

This is the general way it'd be done. The real trick is deciding how and when to call SpecificName(), when to change the item's name var, and so on. It's not an easy task in DM but it could be doable.

Lummox JR
In response to Shadowdarke
Shadowdarke wrote:
An assosiative list would be the best way to store ID values for a number of different individuals. Since the mobs will change as players disonnect and reconnect to the game, you'll want to index the list by something that will always be the same. Probably the client key and character name. In the stat proc, you can display it like so:

obj
var
list/IDpercent = list() // list of identification percentages indexed by mob.key + mob.name

This was my first thought, but I quickly realized it's not doable. BYOND's restriction on the number of lists kills it. Once you have a lot of items, you'll have a lot of lists.

In a broader sense, I think he's looking to set up a Roguelike identification system in which objects have different names depending on what you know about them. I believe DM should be able to do this, since it can do just about anything else, but it will only do it with difficulty. (The problem? Mouseovers, getting and dropping inventory, stat panel displays.... It all adds up.)

Lummox JR
In response to Lummox JR
Ok, thanks for the tips both of you guys, I think you can help me work through this here :)

I am thinking there well be 3 states of every item's ID:
NO_ID ( Name of the group which the item belongs ie-> Sword, Axe, etc.. )
HALF_ID ( Name of the specific group the item belongs, LongSword, Battle Axe, Dagger, Dirk. You get the attack/defense modifiers and basic requirements at this point in time )
FULL_ID ( Name of the item itself & full listing. )

So that you understand more of what I'm trying to do, here's kind of the synopsis of what happens when a player uses the get() proc to get an item off the ground ( Because anything BOUGHT will always be 100% identified ) in a form of pseudo-code ( I don't really have the code yet :) ):
( Each step in the process is prefixed with a '~' )

~mob/pc/M picks up item
~M.Perception is done vs. the complexity of the item ( which is scaled on a 1 - 8 basis, where 8 is the most difficult ) through a formula where the perception of the player ( which is 1 - 20 ) is divided by the complexity of the item + 10.
This results in a HALF_ID setting
~M.Perception is checked again vs. the complexity * 2 with the formula above.
~Item is logged with the appropriate ID levels.
~Item is added to stat panels & what-not.

Items CANNOT be equipped unless they are fully indentified.

So I guess an associative listing would be ok? One key thing, though, is whether I should make it so each player can ID all instances of one item, or if each player should have to ID each item individually.

What I mean by that is that the first case would be similar to this:

PlayerA finds a Copper Long Sword in the dungeon and ID's it sucessfully ( Complexity of 1 ).
Later on PlayerA finds another Copper Long Sword and automatically has it up to the same ID level and chances ID'ing it higher.

or the second case would be:
PlayerA finds a Copper Long Sword in the dungeon and ID's it sucessfully
Later on, PlayerA finds another Copper Long Sword but fails his perception test and thus does not ID THIS Copper Long Sword.

What do you guys think?
In response to ShadowWolf
The first method would be the easiest to impliment, but the second is more realistic (IMO).

The first method would be easy to handle with an associated list on the player mob that lists the ID level of a type indexed by the type.


For the second system, I still think you'd need a list to keep track of all the players who have tried to ID the item.

As Lummox JR noted, an extra list for each item in the game does run the risk of overloading BYOND's limit of 65535 lists in the world. You can cut back on this risk by making it so only identifiable objs have the extra list, and keeping the number of those objs relatively low. (You should have no problem unless you start getting tens of thousands of identifiable objs.)

Another lesson I learned from sd_Text is not to initialize the list until it is needed. sd_Text adds a list var to every atom in the world, which used to lock up worlds with large maps (more than 65000 turfs). Now the list var in sd_Text is uninitialized until it is used, and sd_Text works smoothly in any sized world.

obj
identifiable
var
list/IDlevel // not initialized until needed

proc
getIDlevel(mob/M)
if(!IDlevel) return 0 // or whatever the unIDed level is
return IDlevel[M.key + M.name]

setIDlevel(mob/M, level)
if(!IDlevel) IDlevel = new()
IDlevel[M.key + M.name] = level

Another note, you may want to index it by something a little more complex, like "[ckey]&[ckey(name)]" instead of key+name so that the program knows that "Shadowdarke" playing the character "Bob" is different from "Shadow" playing the character "darkeBob". The ckey() proc strips out special characters like & so that people can't screw it up by using & in their name.
In response to Shadowdarke
Yeah, I figured the 1st would be more easily done, but less fun :p

I wanna do the second m'self, but I kinda wanted to see what other's though too. So basically, each obj that CAN be indentified, which I think would be reduced to any item over complexity level 1, so that's 2-8 in the following groups:
Weapon
Armor
Shield
Boots
Gloves
Belt
Potions
Tombs
Globes
Rocks
with each having somewhere between 50 - 75 items, save for Tombs, Globes, and Rocks, which will probably only have 15 - 20.

So we're looking at 660 lists while at least one instance of the object exists.

I have 4 lists per PC, so in a given virtual simulation where I have 10 PC's and a random instance of indentifiable objects between 500 and 1000, I'm looking at a total of 1040 lists. This is a pretty realistic situation, considering that each dungeon level is only populated when a person is ON the dungeon level. When someone leaves, the objects on that Dungeon Level are removed from existance and re-generated when a person REENTERS the dungeon area ( this presents a short period of lag whenever someone enters a Dungeon Level for the presumed FIRST time, but it's worth it to make sure the dungeons are properly populated. ). But if anyone has any better ideas for that, please share :)

But the thing is that any item that hits the general store does NOT need to have this list because it is auto-identified ( you pay for the cost of identification out of the sell price )...

But umm...for further information, my game is based off another game called Mordor, which is what I call semi-roguelike. It's NOT ASCII graphical, and the Dungeon levels themselves AREN'T randomized. The items, monsters, and traps however, are. I'm using the same system, except I probably will pregenerate random levels :)

Anyways, so basically I can impliment it by just giving the object which can be identified an associative list, which holds the ckey+cname of each individual who's posessed it. Now, can I remove this list and have the game not generate run-time errors? Because once it's hit the general store, I want it to be ID'd ( so that it can be sold properly and not take up so much space ). The general store actually has limited stocks on these kinds of items as well, so this is important.