/**
* Copyright Glidias ( http://wonderfl.net/user/Glidias )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/nJf1
*/
package
{
import com.bit101.components.HBox;
import com.bit101.components.Label;
import com.bit101.components.NumericStepper;
import com.bit101.components.VBox;
// import de.polygonal.math.PM_PRNG;
import flash.display.Sprite;
import flash.events.Event;
/**
* A way to randomise characters' stats in a tactics/strategy RPG.
* Testing random character stat progression based off character class weights.
* @author Glenn Ko
*/
public class RandCharacterProgressionTest extends Sprite
{
/* // Character class: Pirate Skirmisher
private var className:String = "Pirate Skirmisher";
private var weights:Array = [
.75, // Strength
2, // Dexterity
.75, // Constitution
1, // Speed
1, // Perception
.25 // Intelligence
]
// starting level 1 bonuses
private var bonuses:Array = [
0, // Strength
2, // Dexterity
0, // Constitution
2, // Speed
1, // Perception
0 // Intelligence
]
*/
/* // Character class: Indigenous Native
private var className:String = "Indigenous Native";
private var weights:Array = [
.7, // Strength
1, // Dexterity
.25, // Constitution
1, // Speed
.7, // Perception
2 // Intelligence
]
// starting level 1 bonuses
private var bonuses:Array = [
0, // Strength
1, // Dexterity
0, // Constitution
2, // Speed
0, // Perception
2 // Intelligence
]
*/
///* // Character class: Knight
private var className:String = "Knight";
private var weights:Array = [
2.5, // Strength
1, // Dexterity
1.5, // Constitution
.3 // Speed
.5, // Perception
.5 // Intelligence
]
// starting level 1 bonuses
private var bonuses:Array = [
3, // Strength
0, // Dexterity
2, // Constitution
0, // Speed
0, // Perception
0 // Intelligence
]
//*/
// -------------------------------
private var statLabels:Array = [
"Strength",
"Dexterity",
"Constitution",
"Speed",
"Perception",
"Intelligence"
];
private var startingBaseValues:Array = [
5, // Strength
5, // Dexterity
5, // Constitution
5, // Speed
5, // Perception
5 // Intelligence
]
private var curValues:Vector.<Number> = new Vector.<Number>(statLabels.length, true);
private var curValueDisplays:Array = [];
private var levelStepper:NumericStepper;
private var randSeed:int = Math.random()*PM_PRNG.MAX;
private var _statDisplay:VBox;
private var prng:PM_PRNG = new PM_PRNG();
private var WEIGHTS_TOTAL:Number;
public function RandCharacterProgressionTest()
{
new Label(this, 0, 0, className+" | Level:");
levelStepper = new NumericStepper(this, 35, 15, onLevelStepped);
levelStepper.minimum = 1;
levelStepper.maximum = 20;
levelStepper.value = 1;
_statDisplay = new VBox(this,5, 37);
for (var i:int = 0; i < statLabels.length; i++) {
curValueDisplays.push( getStatDisplay( statLabels[i] ) );
}
onCharacterChange();
onLevelStepped();
}
private function onCharacterChange():void
{
recalculateWeights();
}
private function recalculateWeights():void {
var weight:Number;
var i:int;
var numUndeclaredWeights:Number = 0;
var totalDeclaredWeight:Number = 0;
for (i = 0; i < statLabels.length; i++) {
weight = weights[i];
totalDeclaredWeight += weight;
}
WEIGHTS_TOTAL = totalDeclaredWeight;
}
private function getRandomIndex(randRatio:Number, weights:Array ):int {
// return floatRatio * raceNum + 1;
randRatio *= WEIGHTS_TOTAL;
var accum:Number = 0;
var result:int = 0;
for (var i:int = 0; i < weights.length; i++) {
if (randRatio < accum) { // did not meet requirement
break;
}
accum += weights[i];
result = i;
}
return result;
}
private function getStatDisplay(labelTxt:String):Label {
var hBox:HBox = new HBox(_statDisplay);
new Label(hBox, 0, 0, labelTxt +": ");
hBox.height = 16;
return new Label(hBox, 0, 0, "-");
}
private function onLevelStepped(e:Event=null):void
{
var i:int;
var levelsProgressed:int = levelStepper.value - 1;
prng.setSeed(randSeed);
var len:int;
len = statLabels.length;
for (i = 0; i < len; i++) {
curValues[i] = startingBaseValues[i] + bonuses[i];
}
for (i = 0; i < levelsProgressed; i++) {
curValues[ getRandomIndex(prng.nextDouble() , weights) ]++;
}
for (i = 0; i < len; i++) {
curValueDisplays[i].text = String(curValues[i]);
}
}
}
}
/*
* Copyright (c) 2009 Michael Baczynski, http://www.polygonal.de
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* Implementation of the Park Miller (1988) "minimal standard" linear
* congruential pseudo-random number generator.
*
* For a full explanation visit: http://www.firstpr.com.au/dsp/rand31/
*
* The generator uses a modulus constant (m) of 2^31 - 1 which is a
* Mersenne Prime number and a full-period-multiplier of 16807.
* Output is a 31 bit unsigned integer. The range of values output is
* 1 to 2,147,483,646 (2^31-1) and the seed must be in this range too.
*
* David G. Carta's optimisation which needs only 32 bit integer math,
* and no division is actually *slower* in flash (both AS2 & AS3) so
* it's better to use the double-precision floating point version.
*
* @author Michael Baczynski, www.polygonal.de
*/
class PM_PRNG
{
/**
* set seed with a 31 bit unsigned integer
* between 1 and 0X7FFFFFFE inclusive. don't use 0!
*/
public var seed:uint;
public static const MAX:uint = 0X7FFFFFFE;
public function PM_PRNG()
{
seed = 1;
}
/**
* provides the next pseudorandom number
* as an unsigned integer (31 bits)
*/
public function nextInt():uint
{
return gen();
}
/**
* provides the next pseudorandom number
* as a float between nearly 0 and nearly 1.0.
*/
public function nextDouble():Number
{
return (gen() / 2147483647);
}
/**
* provides the next pseudorandom number
* as an unsigned integer (31 bits) betweeen
* a given range.
*/
public function nextIntRange(min:Number, max:Number):uint
{
min -= .4999;
max += .4999;
return Math.round(min + ((max - min) * nextDouble()));
}
/**
* provides the next pseudorandom number
* as a float between a given range.
*/
public function nextDoubleRange(min:Number, max:Number):Number
{
return min + ((max - min) * nextDouble());
}
public function setSeed(v:uint):void
{
if (v == 0) throw new Error("Seed value cannot be zero!");
if (v > MAX) throw new Error("Seed cannot exceed max:"+seed+" /" + MAX);
seed = v;
}
/**
* generator:
* new-value = (old-value * 16807) mod (2^31 - 1)
*/
private function gen():uint
{
//integer version 1, for max int 2^46 - 1 or larger.
return seed = (seed * 16807) % 2147483647;
/**
* integer version 2, for max int 2^31 - 1 (slowest)
*/
//var test:int = 16807 * (seed % 127773 >> 0) - 2836 * (seed / 127773 >> 0);
//return seed = (test > 0 ? test : test + 2147483647);
/**
* david g. carta's optimisation is 15% slower than integer version 1
*/
//var hi:uint = 16807 * (seed >> 16);
//var lo:uint = 16807 * (seed & 0xFFFF) + ((hi & 0x7FFF) << 16) + (hi >> 15);
//return seed = (lo > 0x7FFFFFFF ? lo - 0x7FFFFFFF : lo);
}
}