ID:2533830
 
mob/Login()
htm.add("Kozuma3",444)
htm.add("YLYL",777)
htm.add("Compile2Exe",69)
htm.add("rEkt",1337)
src << htm.get("Kozuma3")


var/htm/htm = new

htm
var list/data = new(11)
htm
proc
hash(string)
string = "[string]"; var sum = 0
for(var/pos = 1 to length(string))
sum += text2ascii(string,pos)
return (sum % 11) + 1
add(string,value)
var hash = hash(string)
if(!(islist(data[hash])))
data[hash] = list()
data[hash][string] = value

get(string)
return data[hash(string)][string]
String Item Database, used with the above code slightly modified.

Defines.dm
#define STATS(a,b,c,d,e)    list("atk"=##a,"str"=##b,"def"=##c,"rng"=##d,"int"=##e)
#define MELEE list("slot"="Weapon","style"="Melee")
#define RANGED list("slot"="Weapon","style"="Ranged")
#define MAGIC list("slot"="Weapon","style"="Magic")
#define HEAD list("slot"="Head")
#define TORSO list("slot"="Torso")
#define LEGS list("slot"="Legs")
#define FEET list("slot"="Feet")
#define HANDS list("slot"="Hands")
#define MOD(a) list("mod"=##a)
#define TWOHANDED list("twohanded")


Database Itself
var db_size     = 16
var list/db = new(db_size)

world/New()
for(. = 1 to db_size)
db[.] = list()
..()

proc/hash(s)
var r = 0
for(var/p = 1 to length(s)){r += text2ascii(s,p)}
return (r % db_size) + 1

proc
db_add(item,value) {db[hash(item)][item] = value}
db_get(item) {return db[hash(item)][item]}
db_mix(item1,item2)
var id = "[item2] [item1]", list/c = new
var list/a = db_get(item1), list/b = db_get(item2)
if("mod" in b)
var mul = b["mod"]
for(var/i in a)
if(isnum(a[i])){c[i] = round(a[i]*mul)}
else c[i] = a[i]
c.Remove("mod")
db[hash(id)][id] = c
db_deb(CH)
var list/l, list/q, p, i, u
if(CH)
p = CH; world << "[p]"; l = db[p]
for(i in l)
q = l[i]; world << " [i] = ([jointext(q," ")])"
for(u in q) {world << " [u] = [q[u]]"}
else
for(p = 1 to db_size)
world << "[p]"; l = db[p]
for(i in l)
q = l[i]; world << " [i] = ([jointext(q," ")])"
for(u in q) {world << " [u] = [q[u]]"}
db_itl(list/A,list/B)
var a,b
for(a in A)
for(b in B)
db_mix(a,b)
db_len()
var r = 0
for(var/p = 1 to db_size)
r += db[p].len
return r
Bases
proc/dbi_Bases()
// Melee
db_add("Dagger", MELEE + STATS(5,3,0,0,0))
db_add("Sword", MELEE + STATS(4,4,0,0,0))
db_add("Rapier", MELEE + STATS(5,4,0,0,0))
db_add("Claws", MELEE + STATS(8,4,0,0,0) + TWOHANDED)
db_add("Axe", MELEE + STATS(3,5,0,0,0))
db_add("Mace", MELEE + STATS(2,6,0,0,0))
db_add("Spear", MELEE + STATS(4,8,0,0,0) + TWOHANDED)
db_add("Warhammer", MELEE + STATS(3,9,0,0,0) + TWOHANDED)
// Ranged
db_add("Bow", RANGED + STATS(4,0,0,5,0) + TWOHANDED)
db_add("Longbow", RANGED + STATS(5,0,0,5,0) + TWOHANDED)
db_add("Crossbow", RANGED + STATS(4,0,0,6,0) + TWOHANDED)
// Magic
db_add("Staff", MAGIC + STATS(6,0,0,0,6) + TWOHANDED)
db_add("Wand", MAGIC + STATS(5,0,0,0,3))
db_add("Battlestaff", MAGIC + STATS(5,0,0,0,7) + TWOHANDED)


proc/dbi_Mods()
// Melee
db_add("Iron", MOD(1.00))
db_add("Steel", MOD(1.40))
db_add("Gilded", MOD(2.00))
db_add("Mythril", MOD(2.80))
db_add("Obsidian", MOD(3.80))
db_add("Dragonbone", MOD(5.00))
// Ranged
db_add("Oak", MOD(1.00))
db_add("Maple", MOD(1.40))
db_add("Yew", MOD(2.00))
db_add("Enchanted", MOD(2.80))
db_add("Specter", MOD(3.80))
db_add("Ulterior", MOD(5.00))
// Magic
db_add("Adept", MOD(1.00))
db_add("Wizard", MOD(1.40))
db_add("Mage", MOD(2.00))
db_add("Sage", MOD(2.80))
db_add("Mystical", MOD(3.80))
db_add("Hexmage", MOD(5.00))
Demo
world/New()
..()
var list/melee_tiers = list(
"Iron", "Steel", "Gilded", "Mythril","Obsidian","Dragonbone")
var list/ranged_tiers = list(
"Oak", "Maple", "Yew", "Enchanted","Specter","Ulterior")
var list/magic_tiers = list(
"Adept", "Wizard", "Mage", "Sage","Mystical","Hexmage")
var list/melee_weps = list(
"Dagger","Sword","Rapier","Claws","Axe","Mace","Spear","Warhammer")
var list/ranged_weps = list(
"Bow","Longbow","Crossbow")
var list/magic_weps = list(
"Staff","Wand","Battlestaff")
dbi_Bases()
dbi_Mods()
// Run-time
db_itl(melee_weps, melee_tiers)
db_itl(ranged_weps, ranged_tiers)
db_itl(magic_weps, magic_tiers)

mob/Login()
src << "Item Count: [db_len()]"
All you need is the string/name of the item within the database, and you can retrieve values as such.
var def = db_get("Iron Helm")["def"]
proc/db_add(item,value)     // Adds the item to the db pointing to its value
proc/db_get(item) // Gets all the items variables
proc/db_mix(item1,item2) // Combines both items together; Iron + Dagger = Iron Dagger
proc/db_itl(list/A,list/B) // Combines A and B together calling db_mix on all elements.
proc/db_deb(v) // Shows the entire database, use a number for a specific location.
proc/db_len() // Returns the length of the entire database
Loop Data Structure :D

lds //loop data structure
var list/loops = new
var maxtick, tick
proc
add(ID,TIME,FUNCTION,GLOBAL)
loops[ID] = list(0,TIME,FUNCTION,GLOBAL,list())
join(REF,ID)
loops[ID][5] |= REF
New()
spawn(3)
var list/l,id,o,t=world.tick_lag
for()
sleep(t)
for(id in loops)
l = loops[id]; l[1]--
if(0 >= l[1])
l[1] = l[2]
if(l[4] == TRUE){call(l[3])()}
else {for(o in l[5]){call(o,l[3])()}}

var lds/lds = new
world/New()
lds.add("Clock", 10, /proc/Tick, TRUE)
lds.add("Movement", world.tick_lag, /mob/proc/Movement)

mob/Login()
lds.join(src,"Movement")

mob/proc/Movement()
world << "[name]!"

proc/Tick()
world << "Tick.."
mob/verb/Execute()
var
a = "23089760982704682704987610560195248908029780972439680"
b = "57123857195871905495187045870159875019834691578109435"
src << StrNumAdd(b,a)

#define char_num(p,v) ((length(v) >= p) ? text2num(v[p]) : 0)

proc/StrNumAdd(a,b)
var list/l[(length(a) > length(b) ? length(a) : length(b)) + 8]
var tvr, len = l.len, car
while(len > length(a)){a="0[a]"}
while(len > length(b)){b="0[b]"}
for(var/pos = len to 1 step -1)
tvr = char_num(pos,a) + char_num(pos,b) + car
car = 0
while(tvr > 9){tvr-=10;car++}
l[pos] = tvr
l = jointext(l,"")
while(findtext(l,"0",1,2)){l = copytext(l,2)}
return l


Allows you to be able to use/add giant numbers, 488 digits worked. Good luck making divide and subtract.
In response to Kozuma3
throw EXCEPTION
DM has exceptions now?

I must be missing something because I do bot see how to print decimals.

Also, I have a question: why not .dll or .so instead? Pass back and forth as strings and avoid any overhead from fiddling with lists and converting to string.
In response to Major Falcon
It stores things in binary, and to convert from binary to decimal you need to be able to compute remainders. That code doesn't yet have division, so at the moment there's no way to convert to base ten. The library is not yet finished (I got hung up on something small, I can't remember what) which is why it's not on the hub.

And I wanted to do it entirely in DM.
Oh, and something I forgot to mention which is important is that the reason it has to convert to a string is that in that library data is stored as a list of integers (in essence you can think of it as storing a number in base 216 but in a two's complement sort of analogue). I then break the data up into the "right" way when performing operations, let the processor do the heavy lifting, and then put everything back together in the correct order.

There's a lot of logic in doing it, but the speed gains are substantial. There's a few libraries on the hub that do what Koz's code does—storing things as a string in decimal—but this is much slower. In the projects thread in On Topic I have some speed tests I did too really show the difference. The big one I remember is computing 300! (the factorial of 300, which is 300! = 300*299*298*297*...*4*3*2*1, which is a very, very big number). BigInt computes this in less than a second iirc while these other libraries take 30 seconds or more.

The tradeoff to these operations being so much faster is that converting to decimal representation takes more work since you need to compute remainders. It also means the representation in a list is rather essential to the whole thing

[edit]

Here's a link to one places where I mentioned factorials, though it's actually 150! rather than 300!. Can't find where I compared it against string-based libraries, but I thought it was in there somewhere. Maybe I posted that somewhere else.
Your library is complicated. I tried to put this into terms of your library but I did not download your code to try and compile it.

pif_BigInt/proc/PrintDecimal()
{
// var/BINARY = PrintBinary()
// var/LEN = lentext(BINARY);
var/list/dec = list(0);
var/BITLENGTH = BitLength();

// for(var/c = 1; c <= LEN; ++c)
for(var/b = 0; b < BITLENGTH; ++b)
{
// var/CHAR = BINARY[c];
// var/carry = binchar2num(CHAR);
var/carry = Bit(b);

for(var/i = 1; i <= dec.len; ++i)
{
var/val = (dec[i] * 2) + carry;
dec[i] = val % 10;
carry = round(val / 10);
}

while(carry > 0)
{
dec += carry % 10;
carry = round(carry / 10);
}
}

. = "";
for(var/i = dec.len; i > 0; --i) . = "[.][dec[i]]";
}

proc/binchar2num(var/char)
{
if(char == "0") return 0;
if(char == "1") return 1;
return -1;
}
Here is the original I know works based on https://stackoverflow.com/questions/2652760/ nvert-a-gi-normous-integer-in-string-format-to-hex-format-c/ 2653006#2653006

pif_BigInt/proc/PrintDecimal()
{
var/HEX = PrintHexadecimal();
var/LEN = lentext(HEX);
var/list/dec = list();

for(var/c = 1; c <= LEN; ++c)
{
var/CHAR = HEX[c];
var/carry = hexchar2num(CHAR);

for(var/i = 1; i <= dec.len; ++i)
{
var/val = (dec[i] * 16) + carry;
dec[i] = val % 10;
carry = round(val / 10);
}

while(carry > 0)
{
dec += carry % 10;
carry = round(carry / 10);
}
}

. = "";
for(var/i = dec.len; i > 0; --i) . += "[dec[i]]";
}


proc/hexchar2num(var/char)
{
var/code = text2ascii(char);
if((code >= 48) && (code <= 57)) return (code - 48);
if((code >= 97) && (code <= 102)) return (code - 87);

return -1; //some error code, idk
}
In response to Popisfizzy
Popisfizzy wrote:
It stores things in binary, and to convert from binary to decimal you need to be able to compute remainders. That code doesn't yet have division, so at the moment there's no way to convert to base ten. The library is not yet finished (I got hung up on something small, I can't remember what) which is why it's not on the hub.

It's a fantastic library to have done in DM. I would have used C considering speed is likely important when dealing with large numbers, but your proof-of-concept is sufficiently and impressively fast; I am bewildered.

One thing to note is that the underlying bitset is not abstracted away. Any performance considerations for that? I would think you have a library laying around somewhere.

In response to Major Falcon
Hmm. In retrospect, that approach is stupidly obvious and I can't believe I overlooked it before. I'll have to update the related method in my pif_LongInt library, because it's much faster than computing remainders.

It's a fantastic library to have done in DM. I would have used C considering speed is likely important when dealing with large numbers, but your proof-of-concept is sufficiently and impressively fast; I am bewildered.

Thank you, but I think for matters you'd want to use large integers for such as something like RSA I still feel it's far too slow.

It was an interesting project, nevertheless. I had the idea for quite some time, but it was only a couple years ago when I was between leaving school and finding a job that I got around to actually doing it. Had to learn more about how integers are represented in memory, since I only knew a little bit about it at the time. Binary I knew of course, but other details took more looking into.

One thing to note is that the underlying bitset is not abstracted away. Any performance considerations for that? I would think you have a library laying around somewhere.

Can you clarify what you mean, exactly?
As a bitset datum containing an array of bytes, indexed by the bit. Usually used for holding a large array of bit flags in a compact space, but they have many purposes and speed advantages over using bytes for booleans due to being closer in memory.

I was just wondering because the logic is already on your code. Last time I was here I developed a bitset library; I could have sworn you had one on the hub.

[Edit]
And therefore I asked because there must be a reason it wasn't abstracted into its own based on my assumptions.
In response to Major Falcon
Yeah, to my knowledge I've never had any library for that. If I ever go back to working on BigInt, though, I might put in a few helper methods to make it easier to use as a bitset since it wouldn't be all that hard
var cult = "join my discord"
Thanks for posting all this code here, Kozuma.
May I ask: what is your motivation?
Page: 1 2