Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

A small Deity AI class system

by holyghost (Sexton)
on Nov 05, 2017 at 14:49 UTC ( #1202777=perlmeditation: print w/replies, xml ) Need Help??

### Copyright (C) The Holy Ghost 2017 ###This program is released under the GPL 3.0 and artistic license 2.0 +. package HollyGameAI::AIInterface; our @ISA = "Interface"; sub AIInterface { my $class = shift; $self = $class->SUPER::Interface(qw(@_)); ### e.g. qw(swim fly +) bless $self, $class; } ### Copyright (C) The Holy Ghost 2017 ###This program is released under the GPL 3.0 and artistic license 2.0 +. package HollyGameAI::Factory; our @ISA = "HollyGameAI::Interface"; sub Factory { my $class = shift; my $self = $class->SUPER::Interface(@_); ### include abstract method names return bless $self, $class; } ### Copyright (C) The Holy Ghost 2017 ###This program is released under the GPL 3.0 and artistic license 2.0 +. ### with thanks to gregorovius from perlmonks package HollyGameAI::Interface; use Carp; sub Interface { my $class = shift; my $self = {inheritors => (), abstract_methods => shift, ### e.g. qw(swim fl +y) }; bless $self, $class; } sub import { my $method = caller; push (@{ $self->{inheritors}}, $method); } sub INIT { my $bad = 0; for my $class ($self->{inheritors}) { for my $meth ($self->{abstract_methods}) { no strict 'refs'; unless (defined &{"${class}::$meth"}) { $bad = 1; warn "HolyGameAI : Class $class should + implement HolyGameAI Interface but does not define $meth.\n"; } } } croak "HollyGameAI : Source compilation aborted at interface b +inding time\n" if $bad; } ### Copyright (C) The Holy Ghost 2017 ###This program is released under the GPL 3.0 and artistic license 2.0 +. package HollyGameAI::MutualExclusiveAI; use lib "../HollyGameAI"; use Factory; sub MutualExclusiveAI { my $class = shift; my $self = { aiclass => HollyGameAI::Factory->Factory(@_) }; bless $self, $class; } ### Copyright (C) The Holy Ghost 2017 ###This program is released under the GPL 3.0 and artistic license 2.0 +. package HollyGameAI::MutualExclusiveDeityAI; our @ISA = "MutualExclusiveAI"; sub MutualExclusiveDeityAI { my $class = shift; my $self = $self->SUPER::MutualExclusiveAI(qw(cast donate swim + fly empower)); bless $self, $class; } ### Copyright (C) The Holy Ghost 2017 ###This program is released under the GPL 3.0 and artistic license 2.0 +. package HollyGameAI::RNG; ### Random Number God, dice class sub RNG { my $class = shift; my $self = { dx => 0 }; return bless $self, $class; } sub set { my ($self, $dxx) = @_; $self->{dx} = $dxx; } sub rollDX { my $self = shift; return rand($dx); } sub rollD1 { my $self = shift; return rand(1); } sub rollD3 { my $self = shift; return rand(3); } sub rollD6 { my $self = shift; return rand(6); } sub rollD10 { my $self = shift; return rand(10); } sub rollD20 { my $self = shift; return rand(20); } sub rollPreviousDX { my $self = shift; return rand($self->{dx}); } sub roll { my ($self, $dxx) = shift; $self->set($dxx); given ($self->{dx}) { when ($_ = 0) { return 0; } when ($_ == 1) { return rollD1; } when ($_ == 3) { return rollD3; } when ($_ == 6) { return rollD6; } when ($_ == 10) { return rollD10; } when ($_ == 20) { return rollD20; } } return 0; }

Replies are listed 'Best First'.
Re: A small Deity AI class system
by roboticus (Chancellor) on Nov 05, 2017 at 15:57 UTC

    holyghost:

    A few suggestions:

    • You should describe what your code is intended to be used for.
    • It's easy to learn POD markup, so I'd suggest adding some documentation as needed.
    • Rather than post it as a single block of code, you should split it into the various source files so potential users have a chance to actually be able to use your module(s). Be sure to put the source file name in the blocks, so they can be saved with a proper name. Something like:
      File HollyGameAI/AIInterface.pm:
      # HollyGameAI/AIInterface.pm ### Copyright (C) The Holy Ghost 2017 ### This program is released under the GPL 3.0 and Artistic License 2. +0. package ...

      File HollyGameAI::Factory.pm:
      # HollyGameAI/AIInterface.pm ### Copyright (C) The Holy Ghost 2017 ### This program is released under the GPL 3.0 and Artistic License 2. +0. package ...
    • You should have included some test and/or demonstration code to give people a feel for what it can and cannot do.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: A small Deity AI class system
by Your Mother (Chancellor) on Nov 05, 2017 at 17:52 UTC

    Your dice routines might not be doing what you think. They don't conform to regular RPG expectations anyway.

    This is closer to what I'd expect and write. Since you don't need or use the object, there is no reason to have it at all. rand(10) can never be 10 and will sometimes be (effectively) 0. I personally always omit explicit return statements unless they control flow in subroutine logic.

    sub rollD10 { 1 + int( rand(10) ) }
      I know about the rand() function, you get 10 cases in rollD10, without having to do a + 1 (it also returns faster). Zeroes could lead out to a non-hit e.g. on a Enemy Non Player Character. The meaning of the RNG class is to use it within e.g. the empower method which can be made through e.g. the water god Umberlee with swim and so on (derived classes from the Deity AI class.) Then the split method using ^### should split up the files for you in a small program that's left as an exercise. HTH

        I really encourage you to Benchmark instead of assuming. You will get surprises somewhat often. And assuming a simple arithmetic op is a performance killer seems silly. It took 10 million iterations to even be able to get this to benchmark without complaining it wasn't enough to be sure; and while a fifteenth of a millionth of a second is indeed three times faster than a fifth of a millionth of a second… does it actually matter on any level for the application in question?

        moo@cow[483]~>perl pm-dice use strictures; use Benchmark "cmpthese"; sub d10 { my $self = shift; return rand(10); } sub d10_2 { rand(10) } sub d10_3 { 1 + int( rand(10) ) } sub d10_4 { 1 + rand(10) } cmpthese( 10_000_000, { orig => \&d10, orig_simple => \&d10_2, int_plus_one => \&d10_3, plus_one => \&d10_4, }); __END__ Rate orig int_plus_one plus_one orig_si +mple orig 4048583/s -- -19% -38% + -74% int_plus_one 5000000/s 24% -- -24% + -68% plus_one 6578947/s 62% 32% -- + -59% orig_simple 15873016/s 292% 217% 141% + --
        I was wrong in saying that the RNG was faster with 0, this is not assembler shifted in perl. The system was made on FreeBSD 11.0 and Debian GNU/Linux. Now I've tried to make some main characters by rewriting the Deity class :
        package HollyGameAI::MutualExclusiveDeityAI; our @ISA = "MutualExclusiveAI"; sub MutualExclusiveDeityAI { my $class = shift; my $self = $class->SUPER::MutualExclusiveAI(@_); bless $self, ref($class) || $class; }
        Here are some examples for use as Deities for the main character _NOTE_ however that I do not know how to override the Factory with inherited methods inside the MutualExclusiveAI class, I cannot repost however with that as a question (the clue of the post however) :
        package HollyGameAI::MutualExclusiveAI; use lib "../HollyGameAI"; use Factory; sub MutualExclusiveAI { my ($class) = shift; my $self = { aiclass => HollyGameAI::Factory->Factory(@_) }; bless $self, ref($class) || $class; }
        Here are Moradin and Umberlee classes based on the system :
        package HollyGameAI::Umberlee; our @ISA = "MutualExclusiveDeityAI"; sub Umberlee { my $class = shift; my $self = $class->SUPER::MutualExclusiveDeityAI(qw(swim empow +er)); bless $self, ref($class) || $class; }
        package HollyGameAI::Moradin; our @ISA = "MutualExclusiveDeityAI"; sub Moradin { my $class = shift; my $self = $class->SUPER::MutualExclusiveDeityAI(qw(empower)); bless $self, ref($class) || $class; }
        Here is a better RNG, the meaning of the superfluous sets is to use the roll previous method without shifting in :
        package HollyGameAI::RNG; ### Random Number God, dice class sub RNG { my $class = shift; my $self = { dx => 0 }; return bless $self, ref($class) || $class; } sub set { my ($self, $dxx) = @_; $self->{dx} = $dxx; } sub rollDX { my $self = shift; return rand($self->{dx}); } sub rollD1 { my $self = shift; return rand(1); } sub rollD3 { my $self = shift; return rand(3); } sub rollD6 { my $self = shift; return rand(6); } sub rollD10 { my $self = shift; return rand(10); } sub rollD20 { my $self = shift; return rand(20); } sub rollPreviousDX { my $self = shift; return rand($self->{dx}); } sub roll { my ($self, $dxx) = @_; $self->set($dxx); given ($self->{dx}) { when ($_ = 0) { return 0; } when ($_ == 1) { return rollD1; } when ($_ == 3) { return rollD3; } when ($_ == 6) { return rollD6; } when ($_ == 10) { return rollD10; } when ($_ == 20) { return rollD20; } } return 0; }
Re: A small Deity AI class system
by jahero (Beadle) on Nov 06, 2017 at 08:14 UTC

    Hi there!

    Almost too long to read without further explanation, however - let me provide brief feedback based on what I have seen in package HollyGameAI::RNG. Please note that I am writing this without knowledge of context.

    Mistake in sub *rollDX*.

    Global symbol "$dx" requires explicit package name (did you forget to declare "my $dx"?) at test.pl line 22

    Class constructor is usually named *new*. In your code, you are using constructor named RNG, which of course works, however this name is not something other people reading your code would expect to be. I would recommend sticking with the name *new* (minus the asterisk of course).

    The way how you pass parameters to your subs is broken.

    Rather complex logic in sub *roll* could be simplified.

    Final tip - it seems you are serious in that your code will be object oriented. If that's the case, I would recommend investing some time and learning one of Perl object oriented frameworks. As for myself, I have been using Moo for some time, and never looked back. Moo

    Don't give up!

    Regards, Jan

Re: A small Deity AI class system
by KurtZ (Pilgrim) on Nov 06, 2017 at 17:10 UTC
    What ?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://1202777]
Approved by herveus
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2017-11-19 07:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    In order to be able to say "I know Perl", you must have:













    Results (278 votes). Check out past polls.

    Notices?