MPL Documentation

Enumators

This sample uses an enumerator, like you might do in a map or maze game, to contain different elements you can loot as you navigate.
program Game.Loot.Example;

uses Math;

const
MaxProbability=1000;

type
   LootType=(Bloodstone, Copper, Emeraldite, Gold, Heronite, Platinum,
             Shadownite, Silver, Soranite, Umbrarite, Cobalt, Iron, Nothing);
   Looter = Class
      Probabilites:Array[0..12] of Longint;
      Choose:private function:LootType of object;
      AsString:private function(l:LootType):String of object;
   End;

function Looter.Choose:LootType;
var
   Loop,randomValue:Word;

Begin
   randomValue:=Random(MaxProbability-1);
   Loop:=0;
   While Probabilites[Loop mod 13]<randomValue do Inc(Loop);
   Result:=LootType(Loop mod 13);
End;

function Looter.AsString(l:LootType):String;
Begin
   Case l of
      Bloodstone:Result:='Bloodstone';
      Copper:Result:='Copper';
      Emeraldite:Result:='Emeraldite';
      Gold:Result:='Gold';
      Heronite:Result:='Heronite';
      Platinum:Result:='Platinum';
      Shadownite:Result:='Shadownite';
      Silver:Result:='Silver';
      Soranite:Result:='Soranite';
      Umbrarite:Result:='Umbrarite';
      Cobalt:Result:='Cobalt';
      Iron:Result:='Iron';
      Else Result:='';
   End;
End;

procedure Looter.Free;
Begin
End;

// Must be listed after all other implementation //
procedure Looter.Init;
Begin
   Randomize;
   with Self do begin // used to link methods to instance!
      Probabilites[0]:=10;
      Probabilites[1]:=77;
      Probabilites[2]:=105;
      Probabilites[3]:=125;
      Probabilites[4]:=142;
      Probabilites[5]:=159;
      Probabilites[6]:=172;
      Probabilites[7]:=200;
      Probabilites[8]:=201;
      Probabilites[9]:=202;
      Probabilites[10]:=216;
      Probabilites[11]:=282;
      Probabilites[12]:=MaxProbability;
      // to avoid RTTI/VMT overhead:
      TMethod(@asstring) := [@Looter.AsString, @self];
      TMethod(@choose) := [@Looter.Choose, @self];
      TMethod(@free) := [@Looter.Free, @self];
   End;
End;

var
   loot:looter;
   n:longint;

begin
   loot.init;
   for n:=0 to 99 do Writeln(Loot.AsString(Loot.choose));
// for n:=0 to 99 do Writeln(Loot.choose); {this used built-in macro to convert Enum to String}
   loot.free;
end.
This is how you define an enumerator:
type
   LootType=(Bloodstone, Copper, Emeraldite, Gold, Heronite, Platinum,
             Shadownite, Silver, Soranite, Umbrarite, Cobalt, Iron, Nothing);
That previous line defines a new variable type called LootType, which now contains a collection or array of minerals and stones for the game. I mention that Enumerators work like an array, as you can see in this next snippet from above, we return the element from LootType as a numeric paramter:
function Looter.Choose:LootType;
var
   Loop,randomValue:Word;

Begin
   randomValue:=Random(MaxProbability-1);
   Loop:=0;
   While Probabilites[Loop mod 13]<randomValue do Inc(Loop);
   Result:=LootType(Loop mod 13);
End;
The last line of the block sets Result to the element of LootType that is the modulos of Loop. If you count the elements of LootType, there are 13 elements. Enumerators normally number the elements 0,1,2,3,4. So, LootType(5) is the same as LootType(Platinum) or using the built-in macro that automagically occurs, you can simply reference Platinum which has the value 5. This last fact is how you can do a case statement against LootType:
function Looter.AsString(l:LootType):String;
Begin
   Case l of
      Bloodstone:Result:='Bloodstone';
      Copper:Result:='Copper';
      Emeraldite:Result:='Emeraldite';
      Gold:Result:='Gold';
      Heronite:Result:='Heronite';
      Platinum:Result:='Platinum';
      Shadownite:Result:='Shadownite';
      Silver:Result:='Silver';
      Soranite:Result:='Soranite';
      Umbrarite:Result:='Umbrarite';
      Cobalt:Result:='Cobalt';
      Iron:Result:='Iron';
      Else Result:='';
   End;
End;
That same routine could be written a number of ways and give you the same result, alternate #1:
function Looter.AsString(l:LootType):String;
Begin
   Case l of
      0:Result:='Bloodstone';
      1:Result:='Copper';
      2:Result:='Emeraldite';
      3:Result:='Gold';
      4:Result:='Heronite';
      5:Result:='Platinum';
      6:Result:='Shadownite';
      7:Result:='Silver';
      8:Result:='Soranite';
      9:Result:='Umbrarite';
      10:Result:='Cobalt';
      11:Result:='Iron';
      Else Result:='';
   End;
End;
alternate #2:
function Looter.AsString(l:LootType):String;
Begin
   Case l of
      LootType(Bloodstone):Result:='Bloodstone';
      LootType(Copper):Result:='Copper';
      LootType(Emeraldite):Result:='Emeraldite';
      LootType(Gold):Result:='Gold';
      LootType(Heronite):Result:='Heronite';
      LootType(Platinum):Result:='Platinum';
      LootType(Shadownite):Result:='Shadownite';
      LootType(Silver):Result:='Silver';
      LootType(Soranite):Result:='Soranite';
      LootType(Umbrarite):Result:='Umbrarite';
      LootType(Cobalt):Result:='Cobalt';
      LootType(Iron):Result:='Iron';
      Else Result:='';
   End;
End;