Building Browsergames: Healing your players (Perl)

We’ve built a banking and combat system, but we haven’t built anything yet that will allow players to heal themselves after combat. Today, we’re going to build that piece of functionality.

Amazingly, we don’t actually need add any new stats to our game – we’ve already got all we need with the Maximum HP and Current HP stats from earlier. That means that we can start building our templates right away, without needing to do any SQL – starting with adding a link to index.tmpl:

 

<p><a href='healer.cgi'>The Healer</a></p>

Now that that’s done, we can create the template for our healing page. There isn’t really anything fancy on it – this is what the entire healer.tmpl template looks like:

 

<html>
<head>
	<title>The Healer</title>
</head>
<body>
	<p>Welcome to the healer. You currently have <strong><!--tmpl_var name='curhp'--></strong> HP out of a maximum of <strong><!--tmpl_var name='maxhp'--></strong>.</p>
	<p>You have <strong><!--tmpl_var name='gold'--></strong> gold to heal yourself with, and it will cost you <strong>1 gold per HP healed</strong> to heal yourself.</p>
	<tmpl_if name='healed'>
		<p>You have been healed for <strong><!--tmpl_var name='healed'--></strong> HP.</p>		
	</tmpl_if>
	<form action='healer.cgi' method='post'>
		<input type='text' name='amount' id='amount' /><br />
		<input type='submit' name='action' value='Heal Me' />
	</form>
	<p><a href='index.cgi'>Back to main</a></p>
	<script type='text/javascript'>
		document.getElementById('amount').focus();
	</script>
</body>
</html>

If you’ve been following along so far, then chances are good that you can take one look at that template and tell exactly what we’re going to be doing with it – but I’ll let you in on the code anwyays. Here’s our starter code to load in the template and populate it with some values:

 

#!/usr/bin/perl -w
 
use strict;
use CGI qw(:cgi);
use HTML::Template;
use DBI;
use config;
use stats;
 
my $query = new CGI;
my %arguments = $query->Vars;
my $cookie = $query->cookie('username+password');
 
my $template = HTML::Template->new(
		filename	=>	'healer.tmpl',
	);
my %parameters;
 
my ($username) = split(/\+/,$cookie);
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass,{RaiseError => 1});
my $sth = $dbh->prepare("SELECT id FROM users WHERE UPPER(username) = UPPER(?)");
$sth->execute($username);
my $userID;
$sth->bind_columns(\$userID);
$sth->fetch;
 
$parameters{gold} = stats::getStat('gc',$userID);
$parameters{curhp} = stats::getStat('curhp',$userID);
$parameters{maxhp} = stats::getStat('maxhp',$userID);
 
$template->param(%parameters);
print $query->header(), $template->output;

With this code in place, now we can write the code that makes our page different from any other page that loads and displays a template. We’re going to add some handling for when a user enters how much they want to get healed. Just like we did for our bank page, we’ll assume that ‘weird’ values mean ‘use the maximum available’ – and then either heal the user to full, or as much as we can with their current gold on hand. Here’s our code to handle healing the user:

 

if(%arguments) {
	my $amount = $arguments{amount};
	my $gold = stats::getStat('gc',$userID);
	my $needed = stats::getStat('maxhp',$userID) - stats::getStat('curhp',$userID);	
	if($amount > $needed || $amount eq '') {
		$amount = $needed;	
	}
	if($amount > $gold) {
		$amount = $gold;	
	}
	stats::setStat('gc',$userID,stats::getStat('gc',$userID) - $amount);
	stats::setStat('curhp',$userID,stats::getStat('curhp',$userID) + $amount);
	$parameters{healed} = $amount;
}

For all that we’ve implemented similar functionality to our banking page from earlier in terms of checking what the user enters, you might notice a slight difference in the tests we perform based on what the user entered. That’s because we first need to make sure that they don’t heal themselves for more than their maximum HP, and then we need to make sure that they can afford to heal themselves for however much they are attempting to. Once the two checks are done, we heal the player for whatever amount possible, and then display a helpful message to show them they’ve been healed – in addition to subtracting the amount healed from their current gold in hand.

And that’s the healer page! People playing the game that we’ve been building can now fight monsters, put their gold in the bank, and heal themselves whenever they get injured. Here’s the code for the healer page, all in one place:

 

#!/usr/bin/perl -w
 
use strict;
use CGI qw(:cgi);
use HTML::Template;
use DBI;
use config;
use stats;
 
my $query = new CGI;
my %arguments = $query->Vars;
my $cookie = $query->cookie('username+password');
 
my $template = HTML::Template->new(
		filename	=>	'healer.tmpl',
	);
my %parameters;
 
my ($username) = split(/\+/,$cookie);
my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost",$dbuser,$dbpass,{RaiseError => 1});
my $sth = $dbh->prepare("SELECT id FROM users WHERE UPPER(username) = UPPER(?)");
$sth->execute($username);
my $userID;
$sth->bind_columns(\$userID);
$sth->fetch;
 
if(%arguments) {
	my $amount = $arguments{amount};
	my $gold = stats::getStat('gc',$userID);
	my $needed = stats::getStat('maxhp',$userID) - stats::getStat('curhp',$userID);	
	if($amount > $needed || $amount eq '') {
		$amount = $needed;	
	}
	if($amount > $gold) {
		$amount = $gold;	
	}
	stats::setStat('gc',$userID,stats::getStat('gc',$userID) - $amount);
	stats::setStat('curhp',$userID,stats::getStat('curhp',$userID) + $amount);
	$parameters{healed} = $amount;
}
 
$parameters{gold} = stats::getStat('gc',$userID);
$parameters{curhp} = stats::getStat('curhp',$userID);
$parameters{maxhp} = stats::getStat('maxhp',$userID);
 
$template->param(%parameters);
print $query->header(), $template->output;