# Doctor Who Simple Chargen

A simple exercise in coding a chargen based on RPG rules. This chargen has security issues in how the secure() function was used. Scroll down for a short explanation of the issue.

```
@dig/teleport Time Lord RPG CharGen

@VA here=#5346

@set here=INHERIT

@Desc here=%R[u(%VA/FN-SHEET, %#)][repeat(-, 78)]%RPoints: [ladd(parse(u(%#/_DW-ABIL), power(after(##, :), 2), |))] in Abilities. [ladd(parse(lattr(%#/_DW-SKILL_*), power(first(get(%#/##), |), 2)))] in Skills. [u(%#/_DW-POINTS)] remaining. %R%RABILITIES: [itemize(u(%VA/ABILS),,and)]. It is suggested one put between 90 and 110 points into Abilities.%R%R +set  to  ... can be between 0 and 6. %R%RSKILLS: Invent your own. They typically hang off of an Ability. 1= Better than normal. 2= Much better than normal. 3= Amazing %R%R +skill/ = ... can be between 0 and 3. %R%R +reset/\[abilities/skills/all\] %R

&ABILS here=Strength Control Size Move Weight Knowledge Determination Awareness

&FN-ROLL here=[if(gt(setr(2, add(setr(0, ladd(%0)), setr(1, abs(sub(die(1, 6), die(1, 6)))))), setr(3, ladd(%1))), %q0 <+%q1> vs Difficulty  %q3=Success <+[sub(%q2, %q3)]>, %q0 <+%q1> vs Difficulty %q3=Failure <[sub(%q2, %q3)]>)]

&FN-GETABIL here=[round(after(grab(u([secure(%0)]/_DW-ABIL), [secure(%1)]*:*, |), :), 0)]

&FN-SETABIL here=[set(%0, _DW-ABIL:[replace(setr(0, u(%0/_DW-ABIL)), setr(1, match(%q0, [secure(%1)]*:*, |)), [before(extract(%q0, %q1, 1, |), :)]:[round(%2, 0)], |)])]

&FN-SHEET here=[center(-= [ucstr(name(%0))]'S +SHEET =-, 78, -)]%R [parse(u(%VA/ABILS), [ljust(##, 20, .)].[ulocal(%VA/FN-GETABIL, %0, ##)][ulocal(%VA/FN-SHEET2, %0, ##)])]%RWounds: [udefault(%0/_DW-WOUNDS, 0)]/[mul(u(%VA/FN-GETABIL, %0, Strength), 2)] %R

&FN-SHEET2 here=[if(words(setr(0, grepi(%0, _DW-SKILL_*, |%1|))), %R[columns(parse(%q0, [ljust(ulocal(%VA/FN-NAMEFIX, after(##, _DW-SKILL_)), 22, .)][first(get(%0/##), |)],,|), 25, |, 3)] ,%R)]

&FN-NAMEFIX here=[parse(edit(lcstr(%0), ~, %b), capstr(##))]

&CMD-SETABIL here=\$+set * to *:@switch/first 0= words(setr(0, grab(u(%VA/ABILS), [secure(%0)]*))), {@pemit %#=GAME> Is '[secure(%0)]' an ability? Try one of [itemize(u(%VA/ABILS),, or)] }, and(isnum(setr(1, secure(%1))), isint(%q1), gte(%q1, 0), lte(%q1, 6)), {@pemit %#=GAME> You can only set your %q0 to an integer between 0 and 6. }, lte([setr(2, sub(power(%q1, 2), power(ulocal(%VA/FN-GETABIL, %#, %q0), 2)))], u(%#/_DW-POINTS)), {@pemit %#=GAME> You only have [u(%#/_DW-POINTS)] to work with, and that'd cost %q2. }, {@pemit %#=GAME> You set your %q0 from [ulocal(%VA/FN-GETABIL, %#, %q0)] to %q1 %RGAME> That [switch(%q2, 0, is free, -*, will get you [abs(%q2)] more points, will cost you %q2 points)], leaving you with [sub(u(%#/_DW-POINTS), %q2)]. [ulocal(%VA/FN-SETABIL, %#, %q0, %q1)][set(%#, _DW-POINTS:[sub(u(%#/_DW-POINTS), %q2)])] }

&CMD-SETSKILL here=\$+skill/* *=*:@switch/first 0 = words(setr(0, grab(u(%VA/ABILS), [secure(%0)]*))), {@pemit %#=GAME> Is '[secure(%0)]' an ability? Try one of [itemize(u(%VA/ABILS),, or)] }, and(isnum(setr(1, secure(%1))), lte(%q1, 3), gte(%q1, 0), isint(%q1)), {@pemit %#=GAME> You can only set a skill to a positive integer of 3 or less. }, lte(power(max(0, %q1), 2), u(%#/_DW-POINTS)), {@pemit %#=GAME> You only have [u(%#/_DW-POINTS)] points to work with, and that'd cost [power(%q1, 2)] points. }, lte(setr(2, first(edit(secure(%2), %b, ~))), 20), {@pemit %#=GAME> Try to make the skill shorter? '[left(secure(%2), 20)]' is how that would have ended up. }, hasattr(%#, _DW-SKILL_%q2), {&_DW-SKILL_%q2 %#=%q1|%q0|[secure(%2)] ;&_DW-POINTS %#=setr(3, sub(u(%#/_DW-POINTS), power(%q1, 2))) ;@pemit %#=GAME> You set your %q0-based skill, '[secure(%2)]' to level %q1. %RGAME> This cost [power(%q1, 2)] points, leaving you with %q3. }, %q1, {&_DW-POINTS %#=setr(3, add(u(%#/_DW-POINTS), power(first(get(%#/_DW-SKILL_%q2), |), 2))) ;&_DW-SKILL_%q2 %#= ;@pemit %#=GAME> You remove your '[secure(%2)]' skill. %RGAME> You currently have %q3 points to work with. }, { &_DW-POINTS %#=setr(3, add(u(%#/_DW-POINTS), sub(power(first(get(%#/_DW-SKILL_%q2), |), 2), power(%q1, 2)))) ;&_DW-SKILL_%q2 %#=%q1|%q0|[secure(%2)] ;@pemit %#=GAME> You reset your %q0-based skill, '[secure(%2)]' to level %q1. %RGAME> You currently have %q3 points to work with. }

&CMD-RESET here=\$+reset/*:think [setq(A, ladd(parse(u(%#/_DW-ABIL), power(after(##, :), 2), |)))] [setq(B, ladd(parse(lattr(%#/_DW-SKILL_*), power(first(get(%#/##), |), 2))))] ;@switch/first 1= match(abilities, [secure(%0)]*), {&_DW-ABIL %#=[parse(u(%VA/ABILS), ##:0,,|)] ;&_DW-POINTS %#=[add(%qA, u(%#/_DW-POINTS))] ;@pemit %#=GAME> You reset your abilities to 0. }, match(skills, [secure(%0)]*), {&_DW-POINTS %#=[add(%qB, u(%#/_DW-POINTS))] ;@wipe %#/_DW-SKILL_* ;@pemit %#=GAME> You reset your skills. }, {&_DW-ABIL %#=[parse(u(%VA/ABILS), ##:3,,|)] ;@wipe %#/_DW-SKILL_* ;&_DW-POINTS %#=100 ;@pemit %#=GAME> You reset all your stuff.}

&CMD-SHEET here=\$+dwsheet*:@pemit %#=[u(%VA/FN-SHEET, if(controls(%#, pmatch(trim(secure(%0)))), pmatch(trim(secure(%0))), %#))][repeat(-, 78)]

&CMD-ROLL here=\$+dwroll * vs *:@switch/first 0= and(isnum(ladd(secure(%0))), isnum(ladd(secure(%1)))), {@pemit %#=GAME> Are you sure you're entering numbers? }, {@remit loc(%#)=GAME> %n rolls [ulocal(%VA/FN-ROLL, secure(%0), secure(%1))] }

You'll want to set the @VA as whatever the dbref of the room is. The %VA thing is so one can move all the functions onto some near-Master Room staff-functions object.

Note also, the skill-setting bit really bites. I was pretty much making it up as I went along, and it could probably use some improvements.
```

Below this point is a note about security issues in this chargen:

```I notice you doing this a lot:

\$cmdpow *:[secure(%0)]

This doesn't work.

"Note: 'say secure(Sneak a peek at Wiz's desc... [get(#1/desc)])' does not produce the expected result because the argument is evaluated BEFORE being processed by secure(), therefore the [get()] call has already been performed."
-HELP SECURE

Notice the part about the argument is evaluated before hand? Same for \$CMD's.
```