git @ Cat's Eye Technologies Corona-Realm-of-Magic / master src / Cloneable.pm
master

Tree @master (Download .tar.gz)

Cloneable.pm @masterraw · history · blame

package Cloneable;

# Coneable and Copyable objects for CARPE DIEM

# Copyright (c)2000-2013, Chris Pressey, Cat's Eye Technologies.
# All rights reserved.
# Distributed under a BSD-style license; see the file LICENSE for more info.

# deep copy the object network involved,
# instancing Dice and Distribution objects in the process
sub clone
{
  my $self = shift;
  my $new = +{}; my $key;
  foreach $key (keys %{$self})
  {
    if (not defined $self->{$key})
    {
      $new->{$key} = undef; next;
    }
    my $r = ref($self->{$key});
    if (not $r)
    {
      $new->{$key} = $self->{$key};
    } elsif ($r eq 'SCALAR')
    {
      $new->{$key} = \${$self->{$key}};
    } elsif($r eq 'ARRAY')
    {
      $new->{$key} = [ @{$self->{$key}} ];
    } elsif($r eq 'HASH')
    {
      # $new->{$key} = +{ %{$self->{$key}} };
      $new->{$key} = Cloneable::clone($self->{$key});  # crafty recursion?
    } elsif($r eq 'CODE')
    {
      $new->{$key} = $self->{$key};  # no way/need to clone a sub
    } elsif($r eq '')
    {
      $new->{$key} = $self->{$key};  # no need to clone a scalar
    } elsif($r eq 'Adj')
    {
      $new->{$key} = $self->{$key};  # no need to clone Adj, no identity involved
    } elsif($r eq 'Dice')
    {
      $new->{$key} = $self->{$key}->roll;  # gen new stat
    } elsif($r eq 'Distribution')
    {
      $new->{$key} = $self->{$key}->pick;  # gen new stat
    } elsif($r eq 'Force' or $r eq 'Resistances' or $key eq 'location' or $key eq 'soul')
    {
      # DON'T clone, as will have embedded Dices and Distributions
      # which must be kept, not instanced.
      $new->{$key} = $self->{$key};  # mirror dat reference
    } else # we assume it is cloneable...
    {
      $new->{$key} = $self->{$key}->clone;  # wow, recursion
    }
    # print "\n$key: $self->{$key} ---> $new->{$key}"; ::getkey;
  }
  bless $new, ref $self;
  return $new;
}

# deep copy the object network involved,
# while NOT instancing Dice and Distribution objects in the process

# this will NOT deep-copy references in unblessed arrays
# also it will NOT deep-copy any blessed reference which is NOT a hash
sub copy
{
  my $self = shift;
  my $new = +{}; my $key;
  foreach $key (keys %{$self})
  {
    if (not defined $self->{$key})
    {
      $new->{$key} = undef; next;
    }
    my $r = ref($self->{$key});
    if (not $r)
    {
      $new->{$key} = $self->{$key};
    } elsif ($r eq 'SCALAR')
    {
      $new->{$key} = \${$self->{$key}};
    } elsif($r eq 'ARRAY')
    {
      $new->{$key} = [ @{$self->{$key}} ];
    } elsif($r eq 'HASH')
    {
      $new->{$key} = +{ %{$self->{$key}} };
    } elsif($r eq 'CODE')
    {
      $new->{$key} = $self->{$key};  # no way/need to clone a sub
    } elsif($r eq '')
    {
      $new->{$key} = $self->{$key};  # no need to clone a scalar
    } else
    {
      if ($self->{$key}->isa('Cloneable') and $r ne 'Region')
      {
        $new->{$key} = $self->{$key}->copy;  # wow, recursion
      } else
      {
        $new->{$key} = $self->{$key};  # implies: un-Cloneables have no identity
      }
    }
  }
  bless $new, ref $self;
  return $new;
}

1;