💾 Archived View for thrig.me › blog › 2024 › 02 › 04 › state.pl captured on 2024-07-09 at 02:10:57.

View Raw

More Information

⬅️ Previous capture (2024-02-05)

-=-=-=-=-=-=-

#!/usr/bin/env perl
# state.pl - a silly game state example
use 5.36.0;
use constant { UPDATE => 0, RENDER => 1, ENTER => 2, EXIT => 3, };

my ( $Player_HP, $Troll_HP );

my $Is_Running = 1;
my @Game_State;
state_push( make_state( \&menu_update, \&menu_render ) );
while ($Is_Running) {
    $Game_State[-1][RENDER]->();
    $Game_State[-1][UPDATE]->();    # no sleep because this blocks
}
exit(1);

sub make_state ( $up, $rend, $enter = undef, $exit = undef ) {
    my $s;
    $s->@[ UPDATE, RENDER, ENTER, EXIT ] = ( $up, $rend, $enter, $exit );
    return $s;
}

sub state_push ($new) {
    $new->[ENTER]->() if defined $new->[ENTER];
    push @Game_State, $new;
}

sub state_pop {
    $Game_State[-1][EXIT]->() if defined $Game_State[-1][EXIT];
    pop @Game_State;
}

sub menu_render {
    say qq{enter "play" or "quit"};
}

sub menu_update {
    my $choice = readline;
    if ( $choice =~ m/(?i)p/ ) {
        state_push(
            make_state( \&game_update, \&game_render, \&game_enter ) );
    } elsif ( $choice =~ m/(?i)q/ ) {
        $Is_Running = 0;
    }
}

sub game_enter {
    $Player_HP = 10;
    $Troll_HP  = 10;
}

sub game_render {
    say qq{"attack" the troll or "flee"};
}

sub game_update {
    my $choice = readline;
    if ( $choice =~ m/(?i)f/ ) {
        say qq{You find yourself back at the main menu...};
        pop @Game_State;
    } elsif ( $choice =~ m/(?i)a/ ) {
        my $roll = int rand(5);
        say "You hit the troll for $roll generic damage units!";
        $Troll_HP -= $roll;
        $roll = int rand(7);
        say "The troll hits you for $roll!";
        $Player_HP -= $roll;
        if ( $Player_HP <= 0 ) {
            say qq{You die...};
            say qq{... and so did the troll, congrats?} if $Troll_HP <= 0;
            state_pop();
            return;
        }
        if ( $Troll_HP <= 0 ) {
            say qq{You win! (this time...)};
            # this of course could instead go to a victory state or back
            # to the menu or whatever
            exit(0);
        }
    }
}