diff --git a/lib/Lacuna/Building/Development.pm b/lib/Lacuna/Building/Development.pm index 16890675..bca838a6 100644 --- a/lib/Lacuna/Building/Development.pm +++ b/lib/Lacuna/Building/Development.pm @@ -29,7 +29,7 @@ sub subsidize_build_queue { if ($empire->essentia < $amount) { confess [1011, "You don't have enough essentia."]; } - my $building = $empire->get_building($self->model_domain, $building_id); + my $building = $empire->get_building($self->model_class, $building_id); $building->subsidize_build_queue($amount); return { build_queue => $building->format_build_queue, -- 2.51.2 From 4a978246096f5eee57677a472c9e881c4f0c0747 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Thu, 8 Apr 2010 15:28:58 -0500 Subject: [PATCH 02/12] more news rules --- lib/Lacuna/Body.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Lacuna/Body.pm b/lib/Lacuna/Body.pm index c7a6cae9..dadc34f3 100644 --- a/lib/Lacuna/Body.pm +++ b/lib/Lacuna/Body.pm @@ -37,7 +37,9 @@ sub rename { ->not_ok($self->simpledb->domain('body')->count(where => {name_cname=>Lacuna::Util::cname($name), 'itemName()'=>['!=',$body_id]}, consistent=>1)); # name available my $empire = $self->get_empire_by_session($session_id); - $empire->get_body($body_id)->update({name => $name})->put; + my $body = $empire->get_body($body_id); + $body->add_news(200,'In a bold move to show its growing power, %s renamed %s to %s.',$empire->name, $body->name, $name); + $body->update({name => $name})->put; return 1; } -- 2.51.2 From f8cef3e0517205e89327f28111467ee49958e842 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Thu, 8 Apr 2010 15:32:18 -0500 Subject: [PATCH 03/12] apostrophe --- lib/Lacuna/Body.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Lacuna/Body.pm b/lib/Lacuna/Body.pm index dadc34f3..3c8ca41d 100644 --- a/lib/Lacuna/Body.pm +++ b/lib/Lacuna/Body.pm @@ -38,7 +38,7 @@ sub rename { my $empire = $self->get_empire_by_session($session_id); my $body = $empire->get_body($body_id); - $body->add_news(200,'In a bold move to show its growing power, %s renamed %s to %s.',$empire->name, $body->name, $name); + $body->add_news(200,"In a bold move to show it's growing power, %s renamed %s to %s.",$empire->name, $body->name, $name); $body->update({name => $name})->put; return 1; } -- 2.51.2 From cbaae59e0bf47b13f19a9985c088bf55170b1f83 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Thu, 8 Apr 2010 15:40:13 -0500 Subject: [PATCH 04/12] had it backwards --- lib/Lacuna/Body.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Lacuna/Body.pm b/lib/Lacuna/Body.pm index 3c8ca41d..35e90186 100644 --- a/lib/Lacuna/Body.pm +++ b/lib/Lacuna/Body.pm @@ -38,7 +38,7 @@ sub rename { my $empire = $self->get_empire_by_session($session_id); my $body = $empire->get_body($body_id); - $body->add_news(200,"In a bold move to show it's growing power, %s renamed %s to %s.",$empire->name, $body->name, $name); + $body->add_news(200,"In a bold move to show its growing power, %s renamed %s to %s.",$empire->name, $body->name, $name); $body->update({name => $name})->put; return 1; } -- 2.51.2 From 836a4b6b8c0bf6f9620c6b71c72feee8835c84bb Mon Sep 17 00:00:00 2001 From: JT Smith Date: Thu, 8 Apr 2010 23:54:48 -0500 Subject: [PATCH 05/12] spies! --- bin/init_lacuna.pl | 2 +- docs/Intelligence.pod | 143 ++++++++++++++++++++++- lib/Lacuna/Building/Intelligence.pm | 133 +++++++++++++++++++++ lib/Lacuna/DB/Body/Planet.pm | 7 +- lib/Lacuna/DB/Building/Intelligence.pm | 155 +++++++++++++++++++++++-- lib/Lacuna/DB/Building/Network19.pm | 2 +- lib/Lacuna/DB/Building/Shipyard.pm | 2 +- lib/Lacuna/DB/Spies.pm | 55 +++++++++ lib/Lacuna/Tutorial.pm | 2 +- t/Intelligence.t | 69 +++++++++++ var/messages/training_accident.txt | 7 ++ var/messages/tutorial/counter_spy.txt | 4 +- var/messages/tutorial/pawn.txt | 2 +- 13 files changed, 565 insertions(+), 18 deletions(-) create mode 100644 lib/Lacuna/DB/Spies.pm create mode 100644 t/Intelligence.t create mode 100644 var/messages/training_accident.txt diff --git a/bin/init_lacuna.pl b/bin/init_lacuna.pl index 97fd0b97..e9099564 100644 --- a/bin/init_lacuna.pl +++ b/bin/init_lacuna.pl @@ -19,7 +19,7 @@ create_star_map(); close $star_names; sub create_aux_domains { - foreach my $name (qw(empire session build_queue message travel_queue news)) { + foreach my $name (qw(empire session build_queue message travel_queue news spies)) { my $domain = $db->domain($name); say "Deleting existing $name domain."; $domain->delete; diff --git a/docs/Intelligence.pod b/docs/Intelligence.pod index 397bdd25..8415c8b5 100644 --- a/docs/Intelligence.pod +++ b/docs/Intelligence.pod @@ -1,7 +1,148 @@ =head1 Intelligence Methods -Intelligence is accessible via the URL C. +Intelligence Ministry is accessible via the URL C. + +The Intelligence Ministry is where you build and control your spies. The list of methods below represents changes and additions to the methods that all L share. +=head2 view ( session_id, building_id ) + + { + "status" : { ... }, + "building" : { ... }, + "spies" : { + "maximum" : 5, + "current" : 1, + "training_costs" : { + "food" : 100, + "water" : 120, + "energy" : 20, + "ore" : 5, + "waste" : 10, + "time" : 60, + } + }, + } + + +=head2 train_spy ( session_id, building_id, [ quantity ]) + +Allows you to train more spies. + + { + "status" : { get_status() }, + "trained" : 3, + "not_trained" : 2 + } + +The only reason C might be over 0 is if you specify training more spies than you have resources to spend. + +Throws 1013, 1009. + +=head3 session_id + +A session id. + +=head3 building_id + +The unique id of your Intelligence Ministry. + +=head3 quantity + +An integer between 1 and 5. Defaults to 1. + + +=head2 view_spies ( session_id, building_id ) + +Returns the list of spies you have on your roster. + + { + "status" : { get_status() }, + "spies" : { + "id-goes-here" : { + "assignment" : "Idle", + "assigned_to" : { + "body_id" : "id-goes-here", + "name" : "Earth", + }, + "is_available" : 1, # can be reassigned + "available_on" : "01 31 2010 13:09:05 +0600" # if can't be reassigned, this is when will be available + }, + ... + } + } + +Take a look at the C method below for assignment descriptions. + +=head3 session_id + +A session id. + +=head3 building_id + +The unique id of your Intelligence Ministry. + + + +=head2 burn_spy ( session_id, building_id, spy_id ) + +Allows you to eliminate one of your spies from your payroll. + + { + "status" : { get_status() } + } + +=head3 session_id + +A session id. + +=head3 building_id + +The unique id of your Intelligence Ministry. + +=head3 spy_id + +The unique id of the spy you wish to burn. + + + +=head2 assign_spy ( session_id, building_id, spy_id, assignment ) + +Set a spy on a new task. + +=head3 session_id + +A session id. + +=head3 building_id + +The unique id of your Intelligence Ministry. + +=head3 spy_id + +The unique id of the spy you wish to assign. + +=head3 assignment + +A string containing the new assignment name. These are the possible assignments: + +=over + +=item Idle + +Don't do anything. + +=item Counter Intelligence + +Gathering information about what foreign spies are on this planet. + +=item Sting + +Attempt to disrupt the plots of foreign spies on this planet. + +=back + +B You can do good things to enemies, and bad things to allies using these assignments. + =cut \ No newline at end of file diff --git a/lib/Lacuna/Building/Intelligence.pm b/lib/Lacuna/Building/Intelligence.pm index 6becd1d2..df0d3b3d 100644 --- a/lib/Lacuna/Building/Intelligence.pm +++ b/lib/Lacuna/Building/Intelligence.pm @@ -11,6 +11,139 @@ sub model_class { return 'Lacuna::DB::Building::Intelligence'; } +sub view_spies { + my ($self, $session_id, $building_id) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $empire->get_building($self->model_class, $building_id); + my %spies; + my $body = $building->body; + my %planets = ( $body->id => $body->name ); + my $spy_list = $building->get_spies(consistent=>1); + while (my $spy = $spy_list->next) { + unless (exists $planets{$spy->on_body_id}) { + $planets{$spy->on_body_id} = $spy->on_body->name; + } + my $available = $spy->is_available; + my $available_on = $spy->format_available_on; + $spies{$spy->id} = { + assignment => $spy->task, + assigned_to => { + body_id => $spy->on_body_id, + name => $planets{$spy->on_body_id}, + }, + is_available=> $available, + available_on=> $available_on, + }; + } + my @assignments = Lacuna::DB::Spies->assignments; + return { + status => $empire->get_status, + spies => \%spies, + possible_assignments => \@assignments, + }; +} + +sub assign_spy { + my ($self, $session_id, $building_id, $spy_id, $assignment) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $empire->get_building($self->model_class, $building_id); + my $spy = $self->simpledb->domain('spies')->find($spy_id); + unless (defined $spy) { + confess [1002, 'No such spy.']; + } + if ($spy->from_body_id ne $building->body_id) { + confess [1013, "You don't control that spy."]; + } + $spy->assign($assignment)->put; + return { + status => $empire->get_status, + }; +} + +sub burn_spy { + my ($self, $session_id, $building_id, $spy_id, $assignment) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $empire->get_building($self->model_class, $building_id); + my $spy = $self->simpledb->domain('spies')->find($spy_id); + unless (defined $spy) { + confess [1002, 'No such spy.']; + } + if ($spy->from_body_id ne $building->body_id) { + confess [1013, "You don't control that spy."]; + } + my $body = $building->body; + if ($body->add_news(10, 'This reporter has just learned that %s has a policy of burning its own loyal spies.', $empire->name)) { + $body->spend_happiness(1000); + $body->put; + $empire->trigger_full_update; + } + $spy->delete; + return { + status => $empire->get_status, + }; +} + +sub train_spy { + my ($self, $session_id, $building_id, $quantity) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $empire->get_building($self->model_class, $building_id); + $quantity ||= 1; + if ($quantity > 5) { + confess [1009, "You can only train 5 spies at a time."]; + } + my $trained = 0; + my $body = $building->body; + $body->tick; + $building = $empire->get_building($self->model_class, $building_id); #might be stale + $building->body($body); + if ($building->level < 1) { + confess [1013, "You can't train spies until your Intelligence Ministry is completed."]; + } + my $costs = $building->training_costs; + SPY: foreach my $i (1..$quantity) { + foreach my $resource (qw(water ore food energy)) { + my $stored = $resource.'_stored'; + unless ($body->$stored($costs->{$resource})) { + last SPY; + } + } + foreach my $resource (qw(water ore food energy)) { + my $spend = 'spend_'.$resource; + $body->$spend($costs->{$resource}); + } + $body->add_waste($costs->{waste}); + $building->train_spy($costs->{time}); + $trained++; + } + if ($trained) { + $body->put; + if ($trained == 5) { + $body->add_news(50, '%s has just approved a massive intelligence budget increase.', $empire->name); + } + } + return { + status => $empire->get_status, + trained => $trained, + not_trained => $quantity - $trained, + } +} + +around 'view' => sub { + my ($orig, $self, $session_id, $building_id) = @_; + my $empire = $self->get_empire_by_session($session_id); + my $building = $empire->get_building($self->model_domain, $building_id); + my $out = $orig->($self, $empire, $building); + $out->{spies} = { + maximum => $building->max_spies, + current => $building->spy_count, + training_costs => $building->training_costs, + }; + return $out; +}; + +__PACKAGE__->register_rpc_method_names(qw(view_spies assign_spy train_spy burn_spy)); + + no Moose; __PACKAGE__->meta->make_immutable; diff --git a/lib/Lacuna/DB/Body/Planet.pm b/lib/Lacuna/DB/Body/Planet.pm index f3e29c5c..61d53d02 100644 --- a/lib/Lacuna/DB/Body/Planet.pm +++ b/lib/Lacuna/DB/Body/Planet.pm @@ -202,6 +202,7 @@ sub sanitize { ); $self->ships_travelling->delete; $self->simpledb->domain('travel_queue')->search(where=>{foreign_body_id => $self->id})->delete; + $self->simpledb->domain('spies')->search(where=>{from_body_id => $self->id})->delete; foreach my $attribute (@attributes) { $self->$attribute(0); } @@ -733,20 +734,22 @@ sub add_news { my $headline = shift; my $network19 = $self->network19; if (defined $network19) { - $chance += $network19->level; + $chance += $network19->level * 2; if ($network19->restrict_coverage) { $chance = $chance / $self->command->level; } } if (randint(1,100) <= $chance) { $headline = sprintf $headline, @_; - return Lacuna::DB::News->new( + Lacuna::DB::News->new( simpledb => $self->simpledb, date_posted => DateTime->now, zone => $self->zone, headline => $headline, )->put; + return 1; } + return 0; } diff --git a/lib/Lacuna/DB/Building/Intelligence.pm b/lib/Lacuna/DB/Building/Intelligence.pm index bcbdcd98..4eb08d8a 100644 --- a/lib/Lacuna/DB/Building/Intelligence.pm +++ b/lib/Lacuna/DB/Building/Intelligence.pm @@ -4,8 +4,7 @@ use Moose; extends 'Lacuna::DB::Building'; #__PACKAGE__->add_attributes( -# spies => { isa => 'Int' }, -# counter_spies => { isa => 'Int' }, +# spy_count => { isa => 'Int' }, #); around 'build_tags' => sub { @@ -45,16 +44,156 @@ use constant water_consumption => 7; use constant waste_production => 1; -sub add_counter_spy { - my ($self, $count) = @_; - # do this later - return $self; +sub max_spies { + my ($self) = @_; + return $self->level * 5; +} + +has spy_count => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + return $self->simpledb->domain('spies')->count(where=>{from_body_id => $self->body_id}); + }, +); + +has counter_intelligence => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + return $self->simpledb->domain('spies')->count(where=>{on_body_id => $self->body_id, task=>'Counter Intelligence'}); + }, +); + +has sting => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + return $self->simpledb->domain('spies')->count(where=>{on_body_id => $self->body_id, task=>'Sting'}); + }, +); + +has latest_spy => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + return $self->get_spies( + where => { + available_on => ['>=', DateTime->now], + task => 'training', + }, + order_by => ['available_on'], + consistent => 1, + )->next; + }, +); + +sub get_spies { + my ($self, %options) = @_; + my %where = (from_body_id => $self->body_id); + if ($options{where}) { + $where{'-and'} = $options{where}; + } + my %params = ( + where => \%where, + set => { + from_body => $self->body + }, + ); + if ($options{order_by}) { + $params{order_by} = $options{order_by}; + } + if ($options{consistent}) { + $params{consistent} = 1; + } + return $self->simpledb->domain('spies')->search(%params); } -sub count_counter_spies { - return 0; +has espionage => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + return $self->body->get_buildings_of_class('Lacuna::DB::Building::Espionage')->next; + }, +); + +has security => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + return $self->body->get_buildings_of_class('Lacuna::DB::Building::Security')->next; + }, +); + +has training_multiplier => ( + is => 'rw', + lazy => 1, + default => sub { + my $self = shift; + my $multiplier = $self->level - $self->empire->species->deception_affinity; + if (defined $self->espionage) { + $multiplier += $self->espionage->level; + } + if (defined $self->security) { + $multiplier += $self->security->level; + } + $multiplier = 1 if $multiplier < 1; + return $multiplier; + } +); + +sub training_costs { + my $self = shift; + my $multiplier = $self->training_multiplier; + my $species = $self->empire->species; + return { + water => 550 * $multiplier, + waste => 20 * $multiplier, + energy => 50 * $multiplier, + food => 500 * $multiplier, + ore => 5 * $multiplier, + time => 430 * $multiplier / $species->management_affinity, + }; } +sub train_spy { + my ($self, $time_to_train) = @_; + if ($self->spy_count < $self->max_spies) { + unless ($time_to_train) { + $time_to_train = $self->training_costs->{time}; + } + my $latest = $self->latest_spy; + my $available_on = (defined $latest) ? $latest->available_on->clone : DateTime->now; + $available_on->add(seconds => $time_to_train ); + $self->simpledb->domain('spies')->insert({ + from_body_id => $self->body_id, + on_body_id => $self->body_id, + task => 'Training', + available_on => $available_on, + }); + my $count = $self->spy_count($self->spy_count + 1); + if ($count < $self->level) { + $self->body->add_news(20,'A source inside %s admitted that they are underprepared for the threats they face.', $self->empire->name); + } + } + else { + $self->empire->send_predefined_message( + tags => ['Alert'], + filename => 'training_accident.txt', + params => [$self->body->name], + ); + $self->body->add_news(20,'A source inside %s confided that they lost a brave soul in a training accident today.', $self->empire->name); + } + return $self; +} + + no Moose; __PACKAGE__->meta->make_immutable; diff --git a/lib/Lacuna/DB/Building/Network19.pm b/lib/Lacuna/DB/Building/Network19.pm index f90d9a7a..0592bf86 100644 --- a/lib/Lacuna/DB/Building/Network19.pm +++ b/lib/Lacuna/DB/Building/Network19.pm @@ -56,7 +56,7 @@ use constant happiness_production => 30; sub happiness_consumption { my ($self) = @_; - return ($self->restrict_coverage) ? 20 : 0; + return ($self->restrict_coverage) ? 30 : 0; } no Moose; diff --git a/lib/Lacuna/DB/Building/Shipyard.pm b/lib/Lacuna/DB/Building/Shipyard.pm index 20805ea0..ebfc224a 100644 --- a/lib/Lacuna/DB/Building/Shipyard.pm +++ b/lib/Lacuna/DB/Building/Shipyard.pm @@ -269,7 +269,7 @@ sub check_for_completed_ships { filename => 'ship_blew_up_at_port.txt', params => [$completed_ship->{type}, $self->body->name], ); - $self->body->add_news(100,'A %s exploded on %s controlled planet %s.', $type, $self->empire->name, $self->body->name); + $self->body->add_news(100,'%s was rocked today as a %s exploded at the space port.', $self->body->name, $type); last SHIP; } } diff --git a/lib/Lacuna/DB/Spies.pm b/lib/Lacuna/DB/Spies.pm new file mode 100644 index 00000000..6b9a9024 --- /dev/null +++ b/lib/Lacuna/DB/Spies.pm @@ -0,0 +1,55 @@ +package Lacuna::DB::Spies; + +use Moose; +extends 'SimpleDB::Class::Item'; +use Lacuna::Util qw(format_date); +use DateTime; + +__PACKAGE__->set_domain_name('spies'); +__PACKAGE__->add_attributes( + from_body_id => { isa => 'Str' }, + on_body_id => { isa => 'Str' }, + task => { isa => 'Str' }, + available_on => { isa => 'DateTime' }, +); + +__PACKAGE__->belongs_to('from_body', 'Lacuna::DB::Body::Planet', 'from_body_id'); +__PACKAGE__->belongs_to('on_body', 'Lacuna::DB::Body::Planet', 'on_body_id'); + +sub format_available_on { + my ($self) = @_; + return format_date($self->available_on); +} + +sub is_available { + my ($self) = @_; + if (DateTime->now > $self->available_on) { + if ($self->task eq 'Travelling' || $self->task eq 'Training') { + $self->task('Idle'); + $self->put; + } + return 1; + } + return 0; +} + +use constant assignments => ( + 'Idle', + 'Counter Intelligence', + 'Sting', +); + +sub assign { + my ($self, $assignment) = @_; + unless ($assignment ~~ $self->assignments) { + confess [1009, "You can't assign a spy a task that he's not trained for."]; + } + unless ($self->is_available) { + confess [1013, "This spy is unavailable for reassignment."]; + } + $self->task($assignment); + return $self; +} + +no Moose; +__PACKAGE__->meta->make_immutable; diff --git a/lib/Lacuna/Tutorial.pm b/lib/Lacuna/Tutorial.pm index 52d05f7c..ee7b24d7 100644 --- a/lib/Lacuna/Tutorial.pm +++ b/lib/Lacuna/Tutorial.pm @@ -166,7 +166,7 @@ sub pawn { my $building = $home->get_buildings_of_class('Lacuna::DB::Building::Intelligence')->next; if (defined $building && $building->level >= 1) { $home->add_free_upgrade('Lacuna::DB::Building::Intelligence', 2)->put; - $building->add_counter_spy(1)->put; + $building->train_spy; $self->start('counter_spy'); return undef; } diff --git a/t/Intelligence.t b/t/Intelligence.t new file mode 100644 index 00000000..44cecc34 --- /dev/null +++ b/t/Intelligence.t @@ -0,0 +1,69 @@ +use lib '../lib'; +use Test::More tests => 6; +use Test::Deep; +use Data::Dumper; +use 5.010; +use DateTime; + +use TestHelper; +my $tester = TestHelper->new->generate_test_empire; +my $session_id = $tester->session->id; +my $empire = $tester->empire; +my $home = $empire->home_planet; + + +my $result; + + +my $uni = Lacuna::DB::Building::University->new( + simpledb => $tester->db, + x => 0, + y => -1, + class => 'Lacuna::DB::Building::University', + date_created => DateTime->now, + body_id => $home->id, + body => $home, + empire_id => $empire->id, + empire => $empire, + level => 2, +); +$home->build_building($uni); +$uni->finish_upgrade; + +$home->ore_capacity(5000); +$home->energy_capacity(5000); +$home->food_capacity(5000); +$home->water_capacity(5000); +$home->bauxite_stored(5000); +$home->algae_stored(5000); +$home->energy_stored(5000); +$home->water_stored(5000); +$home->ore_hour(5000); +$home->energy_hour(5000); +$home->algae_production_hour(5000); +$home->water_hour(5000); +$home->put; + +$result = $tester->post('intelligence', 'build', [$session_id, $home->id, 0, 1]); +ok($result->{result}{building}{id}, "built an intelligence ministry"); +my $intelligence = $empire->get_building('Lacuna::DB::Building::Intelligence',$result->{result}{building}{id}); +$intelligence->finish_upgrade; + +$result = $tester->post('intelligence', 'view', [$session_id, $intelligence->id]); +is($result->{result}{spies}{maximum}, 5, "get spy data"); + +$result = $tester->post('intelligence', 'train_spy', [$session_id, $intelligence->id, 3]); +is($result->{result}{trained}, 3, "train a spy"); + +$result = $tester->post('intelligence', 'view_spies', [$session_id, $intelligence->id]); +my ($spy_id) = keys %{$result->{result}{spies}}; +is($result->{result}{spies}{$spy_id}{is_available}, 0, "spy training"); +is($result->{result}{possible_assignments}[0], 'Idle', "possible assignments"); + +$result = $tester->post('intelligence', 'burn_spy', [$session_id, $intelligence->id, $spy_id]); +ok(exists$result->{result}, "burn a spy"); + + +END { + $tester->cleanup; +} diff --git a/var/messages/training_accident.txt b/var/messages/training_accident.txt new file mode 100644 index 00000000..115c3eb6 --- /dev/null +++ b/var/messages/training_accident.txt @@ -0,0 +1,7 @@ +Training Accident +~~~ +Sadly, one of our brave spies died in a training accident today on %s. We are investigating the matter to improve the odds it doesn't happen again. + +Regards, + +Your Humble Assistant diff --git a/var/messages/tutorial/counter_spy.txt b/var/messages/tutorial/counter_spy.txt index d3186aea..2ecbdc31 100644 --- a/var/messages/tutorial/counter_spy.txt +++ b/var/messages/tutorial/counter_spy.txt @@ -1,11 +1,11 @@ Counter Spies ~~~ -Well done. I've been able to get you the plans to upgrade your Intelligence Ministry to level two and I've trained one of your counter spies personally. That should help keep some of your information and resources protected. You should train another counter spy so you have two. The more the merrier when it comes to keeping the bad guys out. +Well done. I've been able to get you the plans to upgrade your Intelligence Ministry to level two and I've trained one of your spies personally. That should help keep some of your information and resources protected. You should train another spy so you have two. Then set one on sting duty and one on counter intelligence. The more the merrier when it comes to keeping the bad guys out. Regards, Tou Re Ell (I'm evil, you just don't know it yet!) Lacuna Expanse Corp -Task: Build a Counter Spy. +Task: Build another spy and assign them duties. Reward: None. diff --git a/var/messages/tutorial/pawn.txt b/var/messages/tutorial/pawn.txt index e74cb0e0..8fa5be24 100644 --- a/var/messages/tutorial/pawn.txt +++ b/var/messages/tutorial/pawn.txt @@ -12,4 +12,4 @@ Tou Re Ell (I wonder if he was called "towel" when he was a child?) Lacuna Expanse Corp Task: Build the Intelligence Ministry. -Reward: A free upgrade for the Intelligence Ministry, plus a Counter Spy. +Reward: A free upgrade for the Intelligence Ministry, plus a spy. -- 2.51.2 From a0d4bd070f7f3eb2ab264f5936d291e99f4313da Mon Sep 17 00:00:00 2001 From: JT Smith Date: Fri, 9 Apr 2010 13:33:00 -0500 Subject: [PATCH 06/12] finished tutorial --- lib/Lacuna/Building/Shipyard.pm | 18 ++++++++- lib/Lacuna/DB/Building/Shipyard.pm | 24 +++-------- lib/Lacuna/DB/Spies.pm | 3 +- lib/Lacuna/Tutorial.pm | 58 ++++++++++++++++++++++++++- t/Tutorial.t | 43 +++++++++++++++++--- var/messages/tutorial/counter_spy.txt | 2 + var/messages/tutorial/explore.txt | 15 +++++++ var/messages/tutorial/observatory.txt | 12 ++++++ var/messages/tutorial/the_end.txt | 10 +++++ var/messages/tutorial/turing.txt | 9 +++++ var/messages/welcome.txt | 2 +- 11 files changed, 168 insertions(+), 28 deletions(-) create mode 100644 var/messages/tutorial/explore.txt create mode 100644 var/messages/tutorial/observatory.txt create mode 100644 var/messages/tutorial/the_end.txt create mode 100644 var/messages/tutorial/turing.txt diff --git a/lib/Lacuna/Building/Shipyard.pm b/lib/Lacuna/Building/Shipyard.pm index c2b621f2..3760555f 100644 --- a/lib/Lacuna/Building/Shipyard.pm +++ b/lib/Lacuna/Building/Shipyard.pm @@ -28,9 +28,25 @@ sub build_ship { my ($self, $session_id, $building_id, $type, $quantity) = @_; my $empire = $self->get_empire_by_session($session_id); my $building = $empire->get_building($self->model_class, $building_id); + my $body = $building->body; + $body->tick; + $building = $empire->get_building($self->model_class, $building_id); #might be stale + $building->body($body); my $costs = $building->get_ship_costs($type); $building->can_build_ship($type, $quantity, $costs); - $building->build_ship($type, $quantity, $costs); + foreach my $key (keys %{ $costs }) { + next if $key eq 'seconds'; + if ($key eq 'waste') { + $body->add_waste($costs->{waste} * $quantity); + } + else { + my $spend = 'spend_'.$key; + $body->$spend($costs->{$key} * $quantity); + } + } + $body->put; + $self->empire->trigger_full_update; + $building->build_ship($type, $quantity, $costs->{seconds}); return { ship_build_queue => $building->format_ship_builds, status => $empire->get_status, diff --git a/lib/Lacuna/DB/Building/Shipyard.pm b/lib/Lacuna/DB/Building/Shipyard.pm index ebfc224a..9c930525 100644 --- a/lib/Lacuna/DB/Building/Shipyard.pm +++ b/lib/Lacuna/DB/Building/Shipyard.pm @@ -120,7 +120,7 @@ sub get_ship_costs { my $species = $self->empire->species; my $manufacturing_affinity = $species->manufacturing_affinity; foreach my $cost (keys %{$costs}) { - if ($cost eq 'time') { + if ($cost eq 'seconds') { $costs->{$cost} = sprintf('%0.f', $costs->{$cost} * $self->time_cost_reduction_bonus($self->level)); } else { @@ -157,35 +157,23 @@ sub can_build_ship { sub build_ship { - my ($self, $type, $quantity, $costs) = @_; + my ($self, $type, $quantity, $time) = @_; $quantity ||= 1; - $costs ||= $self->get_ship_costs($type, $quantity); - my $body = $self->body; - foreach my $key (keys %{ $costs }) { - next if $key eq 'seconds'; - if ($key eq 'waste') { - $body->add_waste($costs->{waste}); - } - else { - my $spend = 'spend_'.$key; - $body->$spend($costs->{$key} * $quantity); - } - } - $body->put; - $self->empire->trigger_full_update; + $time ||= $self->get_ship_costs($type)->{seconds}; my $builds = $self->ship_builds->{queue}; push @{$builds->{queue}}, { type => $type, - seconds_each => $costs->{seconds}, + seconds_each => $time, quantity => $quantity, }; unless (exists $builds->{next_completed}) { - $builds->{next_completed} = DateTime->now->add(seconds => $costs->{seconds})->epoch; + $builds->{next_completed} = DateTime->now->add(seconds => $time)->epoch; } $self->ship_builds($builds); $self->put; } + sub get_next_completed { my $self = shift; my $builds = $self->ship_builds; diff --git a/lib/Lacuna/DB/Spies.pm b/lib/Lacuna/DB/Spies.pm index 6b9a9024..930721e1 100644 --- a/lib/Lacuna/DB/Spies.pm +++ b/lib/Lacuna/DB/Spies.pm @@ -41,7 +41,8 @@ use constant assignments => ( sub assign { my ($self, $assignment) = @_; - unless ($assignment ~~ $self->assignments) { + my @assignments = $self->assignments; + unless ($assignment ~~ @assignments) { confess [1009, "You can't assign a spy a task that he's not trained for."]; } unless ($self->is_available) { diff --git a/lib/Lacuna/Tutorial.pm b/lib/Lacuna/Tutorial.pm index ee7b24d7..250ccbc3 100644 --- a/lib/Lacuna/Tutorial.pm +++ b/lib/Lacuna/Tutorial.pm @@ -181,8 +181,8 @@ sub counter_spy { my $home = $self->empire->home_planet; if ($finish) { my $building = $home->get_buildings_of_class('Lacuna::DB::Building::Intelligence')->next; - if (defined $building && $building->count_counter_spies >= 2) { - $self->start(''); + if (defined $building && $building->counter_intelligence >= 1 && $building->sting >= 1) { + $self->start('observatory'); return undef; } } @@ -191,6 +191,60 @@ sub counter_spy { }; } +sub observatory { + my ($self, $finish) = @_; + my $home = $self->empire->home_planet; + if ($finish) { + my $building = $home->get_buildings_of_class('Lacuna::DB::Building::Observatory')->next; + if (defined $building && $building->level >= 1) { + my $shipyard = $home->get_buildings_of_class('Lacuna::DB::Building::Shipyard')->next; + $shipyard->build_ship('probe',1); + $self->start('explore'); + return undef; + } + } + return { + filename => 'tutorial/observatory.txt', + }; +} + +sub explore { + my ($self, $finish) = @_; + my $empire = $self->empire; + if ($finish) { + if (scalar(@{$empire->probed_stars}) > 1) { + $empire->home_planet->add_free_build('Lacuna::DB::Building::Food::Transporter', 1)->put; + $self->start('the_end'); + return undef; + } + } + return { + filename => 'tutorial/explore.txt', + }; +} + +sub the_end { + my ($self, $finish) = @_; + if ($finish) { + $self->start('turing'); + return undef; + } + return { + filename => 'tutorial/the_end.txt', + }; +} + +sub turing { + my ($self, $finish) = @_; + if ($finish) { + $self->start('turing'); + return undef; + } + return { + filename => 'tutorial/turing.txt', + }; +} + sub drinking_water { my ($self, $finish) = @_; my $empire = $self->empire; diff --git a/t/Tutorial.t b/t/Tutorial.t index 791240b5..ba769258 100644 --- a/t/Tutorial.t +++ b/t/Tutorial.t @@ -1,5 +1,5 @@ use lib '../lib'; -use Test::More tests => 16; +use Test::More tests => 23; use Test::Deep; use Data::Dumper; use DateTime; @@ -259,7 +259,7 @@ $building = Lacuna::DB::Building::SpacePort->new( body => $home, empire_id => $empire->id, empire => $empire, - level => 1, + level => 0, ); $home->build_building($building); $building->finish_upgrade; @@ -276,7 +276,7 @@ $building = Lacuna::DB::Building::Shipyard->new( body => $home, empire_id => $empire->id, empire => $empire, - level => 1, + level => 0, ); $home->build_building($building); $building->finish_upgrade; @@ -293,13 +293,46 @@ $building = Lacuna::DB::Building::Intelligence->new( body => $home, empire_id => $empire->id, empire => $empire, - level => 1, + level => 0, ); $home->build_building($building); $building->finish_upgrade; is($tutorial->finish, 1, 'intelligence'); -sleep 30; +$building->train_spy; + +say "Waiting for spies to finish..."; +sleep 216; + +my $spies = $building->get_spies; +$spies->next->assign('Sting')->put; +$spies->next->assign('Counter Intelligence')->put; +sleep 3; +is($tutorial->finish, 1, 'counter spy'); + +$building = Lacuna::DB::Building::Observatory->new( + simpledb => $db, + x => 1, + y => 1, + class => 'Lacuna::DB::Building::Observatory', + date_created => DateTime->now, + body_id => $home->id, + body => $home, + empire_id => $empire->id, + empire => $empire, + level => 0, +); +$home->build_building($building); +$building->finish_upgrade; +is($tutorial->finish, 1, 'observatory'); + +$empire->add_probe('xxxxx'); +is($tutorial->finish, 1, 'explore'); +is($tutorial->finish, 1, 'the_end'); +is($tutorial->finish, 1, 'turing'); +is($tutorial->finish, 1, 'turing'); +is($tutorial->finish, 1, 'turing'); + END { $tester->cleanup; diff --git a/var/messages/tutorial/counter_spy.txt b/var/messages/tutorial/counter_spy.txt index 2ecbdc31..09294d2e 100644 --- a/var/messages/tutorial/counter_spy.txt +++ b/var/messages/tutorial/counter_spy.txt @@ -2,6 +2,8 @@ Counter Spies ~~~ Well done. I've been able to get you the plans to upgrade your Intelligence Ministry to level two and I've trained one of your spies personally. That should help keep some of your information and resources protected. You should train another spy so you have two. Then set one on sting duty and one on counter intelligence. The more the merrier when it comes to keeping the bad guys out. +I'm unsure how much longer I can keep helping you. Unfortunately, I believe they are wise to me, and with each message I send, they get closer to discovering my identity. Be careful. Trust no one. + Regards, Tou Re Ell (I'm evil, you just don't know it yet!) diff --git a/var/messages/tutorial/explore.txt b/var/messages/tutorial/explore.txt new file mode 100644 index 00000000..21e1a528 --- /dev/null +++ b/var/messages/tutorial/explore.txt @@ -0,0 +1,15 @@ +Above and Beyond +~~~ +Probes are an excellent way for you to explore the surrounding star systems. You never know what you might find when you send out a probe. Perhaps the best part is they'll continue to transmit information back to you for as long as they remain operational. + +Send out the probe we gave you so you can see what or who may be nearby. + +Continue to keep me updated on your progress. + +Regards, + +Tou Re Ell +Lacuna Expanse Corp + +Task: Explore another star system. +Reward: Something special. diff --git a/var/messages/tutorial/observatory.txt b/var/messages/tutorial/observatory.txt new file mode 100644 index 00000000..79e89e98 --- /dev/null +++ b/var/messages/tutorial/observatory.txt @@ -0,0 +1,12 @@ +Observatory +~~~ +For some reason we seem to be lacking the detail in the reports that we normally receive. You wouldn't know anything about that would you? + +By the way, we finally caught the traitor who has been interrupting our conversations. It was no less than my personal assistant! Don't worry, he won't bother us again. + +Now where were we? Oh yes, now I remember. There's very little left for me to teach you, but before I leave you to tend to your empire, there is one more thing that you should know. In order to explore the Expanse you need to start producing probes, and in order to do that you'll need to build an Observatory. This shouldn't be too difficult a task for you given your rate of expansion, but it's a necessary step. + +As usual reply when you've completed this. + +Task: Build an Observatory. +Reward: A probe. diff --git a/var/messages/tutorial/the_end.txt b/var/messages/tutorial/the_end.txt new file mode 100644 index 00000000..4c9b1ede --- /dev/null +++ b/var/messages/tutorial/the_end.txt @@ -0,0 +1,10 @@ +The End +~~~ +Unfortunately, our journey has come to an end. As our final gift, we've shipped you a Subspace Transporter. All you need to do is set it up. The Subspace Transporter allows you to transport resources instantly to anyone else that has one. Unfortunately, this process consumes a tiny amount of Essentia. It's a shame to waste it, but the speed of transport has no parallel. + +We would like very much to be your first trading partner. We have a nearly infinite amount of resources at our disposal, but very little Essentia. If you're willing to part with some Essentia when you come across it, we'll trade with you for any goods that you need. This will be our exclusive deal with you. Keep in mind all the help we've given you to get started. With this in mind, I believe, I hope, that you will consider trading with us whenever you are in need. + +Your Trading Partner, + +Tou Re Ell +Lacuna Expanse Corp diff --git a/var/messages/tutorial/turing.txt b/var/messages/tutorial/turing.txt new file mode 100644 index 00000000..60153b6a --- /dev/null +++ b/var/messages/tutorial/turing.txt @@ -0,0 +1,9 @@ +Thank You +~~~ +Thank you for your kind words. We'd be happy to be your trading partner. Just use the Subspace Transporter we gave you. + +Your Trading Partner, + +Tou Re Ell +Lacuna Expanse Corp + diff --git a/var/messages/welcome.txt b/var/messages/welcome.txt index d3210365..a6fa9968 100644 --- a/var/messages/welcome.txt +++ b/var/messages/welcome.txt @@ -11,5 +11,5 @@ Regards, Tou Re Ell Lacuna Expanse Corp -Task: Rename your planet. +Task: Rename your planet and reply to this message. Reward: A free building. -- 2.51.2 From 3e1042c1058069f4121bbc60b7fdbe9922c63837 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Fri, 9 Apr 2010 14:00:29 -0500 Subject: [PATCH 07/12] added essentia to tutorial --- lib/Lacuna/DB/Empire.pm | 5 +++++ lib/Lacuna/Tutorial.pm | 17 ++++++++++++++++- t/Tutorial.t | 9 ++++++++- var/messages/tutorial/essentia.txt | 16 ++++++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 var/messages/tutorial/essentia.txt diff --git a/lib/Lacuna/DB/Empire.pm b/lib/Lacuna/DB/Empire.pm index 6458fe73..a76427a7 100644 --- a/lib/Lacuna/DB/Empire.pm +++ b/lib/Lacuna/DB/Empire.pm @@ -35,6 +35,11 @@ __PACKAGE__->add_attributes( needs_full_update => { isa => 'Str', default=>0 }, tutorial_stage => { isa => 'Str', default=>'explore_the_ui' }, tutorial_scratch => { isa => 'Str' }, + food_boost => { isa => 'DateTime' }, + water_boost => { isa => 'DateTime' }, + ore_boost => { isa => 'DateTime' }, + energy_boost => { isa => 'DateTime' }, + happiness_boost => { isa => 'DateTime' }, ); # personal confederacies diff --git a/lib/Lacuna/Tutorial.pm b/lib/Lacuna/Tutorial.pm index 250ccbc3..568774e3 100644 --- a/lib/Lacuna/Tutorial.pm +++ b/lib/Lacuna/Tutorial.pm @@ -366,7 +366,7 @@ sub fool { if ($finish) { if ($home->food_hour >= $empire->tutorial_scratch) { $home->add_free_upgrade('Lacuna::DB::Building::Food::Reserve', 2)->put; - $self->start('energy'); + $self->start('essentia'); return undef; } } @@ -381,6 +381,21 @@ sub fool { }; } +sub essentia { + my ($self, $finish) = @_; + my $empire = $self->empire; + if ($finish) { + my $now = DateTime->now; + if ($empire->food_boost >= $now && $empire->water_boost >= $now && $empire->ore_boost >= $now && $empire->energy_boost >= $now) { + $self->start('energy'); + return undef; + } + } + return { + filename => 'tutorial/essentia.txt', + }; +} + sub energy { my ($self, $finish) = @_; my $empire = $self->empire; diff --git a/t/Tutorial.t b/t/Tutorial.t index ba769258..7a5c82aa 100644 --- a/t/Tutorial.t +++ b/t/Tutorial.t @@ -1,5 +1,5 @@ use lib '../lib'; -use Test::More tests => 23; +use Test::More tests => 24; use Test::Deep; use Data::Dumper; use DateTime; @@ -179,6 +179,13 @@ $home->build_building($building); $building->finish_upgrade; is($tutorial->finish, 1, 'fool'); +my $future = DateTime->now->add(hours=>1); +$empire->food_boost($future); +$empire->water_boost($future); +$empire->energy_boost($future); +$empire->ore_boost($future); +is($tutorial->finish, 1, 'essentia'); + $building = Lacuna::DB::Building::Energy::Geo->new( simpledb => $db, diff --git a/var/messages/tutorial/essentia.txt b/var/messages/tutorial/essentia.txt new file mode 100644 index 00000000..d70a2087 --- /dev/null +++ b/var/messages/tutorial/essentia.txt @@ -0,0 +1,16 @@ +Essentia +~~~ +You may remember I told you that the entire Lacunan economy depends upon Essentia. I've just given you some of our precious supply. They'd kill me if they knew that I gave it to you. + +Essentia is both rare and powerful. Our entire race spends their waking hours trying to acquire more. If you have it, you're the most powerful species in the Expanse. Essentia has rare properties that allow plants to grow more hearty and machinery to work more efficiently. It can even be used in various chemical processes to transform one element into another. It's the closest thing I've seen to magic. + +Spend some of the Essentia I've given you to boost your production of water, energy, food, and ore. Once you've done this let me know. + +Regards, + +Tou Re Ell (TRE in TLE working for LEC, and that's enough initials for me! Hey that rhymes!) +Lacuna Expanse Corp + +Task: Spend some essentia to boost your production of water, energy, food, and ore. +Reward: None. + -- 2.51.2 From abe5e9c4e12d6a5f9cd36f34cc3d3537f8892c25 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Fri, 9 Apr 2010 17:08:49 -0500 Subject: [PATCH 08/12] added boosts --- docs/Empire.pod | 102 +++++++++++++++++++++++++++++++++++ lib/Lacuna/DB/Body/Planet.pm | 52 +++++++++++++++++- lib/Lacuna/Empire.pm | 64 +++++++++++++++++++++- 3 files changed, 215 insertions(+), 3 deletions(-) diff --git a/docs/Empire.pod b/docs/Empire.pod index ce7435f9..b3db0e6b 100644 --- a/docs/Empire.pod +++ b/docs/Empire.pod @@ -340,5 +340,107 @@ A message to indicate what you're doing, how you're feeling, or other status ind +=head2 view_boost ( session_id ) + +Shows the dates at which boosts have expired or will expire. Boosts are subsidies applied to various resources using essentia. + + { + "status" : { get_status() }, + "boosts" : { + "food" : "01 31 2010 13:09:05 +0600", + "ore" : "01 31 2010 13:09:05 +0600", + "energy" : "01 31 2010 13:09:05 +0600", + "happiness" : "01 31 2010 13:09:05 +0600", + "water" : "01 31 2010 13:09:05 +0600", + } + } + +=head3 session_id + +A session id. + + + +=head2 boost_food ( session_id ) + +Spends 5 essentia, and boosts food production on all planets for 7 days. If a boost is already underway, calling again will add 7 more days. + + { + "status" : { get_status() }, + "food_boost" : "01 31 2010 13:09:05 +0600", + } + +Throws 1011. + +=head3 session_id + +A session id. + + +=head2 boost_water ( session_id ) + +Spends 5 essentia, and boosts water production on all planets for 7 days. If a boost is already underway, calling again will add 7 more days. + + { + "status" : { get_status() }, + "water_boost" : "01 31 2010 13:09:05 +0600", + } + +Throws 1011. + +=head3 session_id + +A session id. + + +=head2 boost_energy ( session_id ) + +Spends 5 essentia, and boosts energy production on all planets for 7 days. If a boost is already underway, calling again will add 7 more days. + + { + "status" : { get_status() }, + "energy_boost" : "01 31 2010 13:09:05 +0600", + } + +Throws 1011. + +=head3 session_id + +A session id. + + +=head2 boost_ore ( session_id ) + +Spends 5 essentia, and boosts ore production on all planets for 7 days. If a boost is already underway, calling again will add 7 more days. + + { + "status" : { get_status() }, + "ore_boost" : "01 31 2010 13:09:05 +0600", + } + +Throws 1011. + +=head3 session_id + +A session id. + + +=head2 boost_happiness ( session_id ) + +Spends 5 essentia, and boosts happiness production on all planets for 7 days. If a boost is already underway, calling again will add 7 more days. + + { + "status" : { get_status() }, + "happiness_boost" : "01 31 2010 13:09:05 +0600", + } + +Throws 1011. + +=head3 session_id + +A session id. + + + =cut diff --git a/lib/Lacuna/DB/Body/Planet.pm b/lib/Lacuna/DB/Body/Planet.pm index 61d53d02..85602605 100644 --- a/lib/Lacuna/DB/Body/Planet.pm +++ b/lib/Lacuna/DB/Body/Planet.pm @@ -6,7 +6,6 @@ use Lacuna::Constants qw(FOOD_TYPES ORE_TYPES); use List::Util qw(shuffle); use Lacuna::Util qw(to_seconds randint); use DateTime; -use Lacuna::DB::News; no warnings 'uninitialized'; __PACKAGE__->add_attributes( @@ -92,8 +91,11 @@ __PACKAGE__->add_attributes( shake_stored => { isa => 'Int', default=>0 }, beetle_stored => { isa => 'Int', default=>0 }, freebies => { isa => 'HashRef' }, + boost_enabled => { isa => 'Str' }, ); +# RELATIONSHIPS + __PACKAGE__->belongs_to('empire', 'Lacuna::DB::Empire', 'empire_id'); __PACKAGE__->has_many('regular_buildings','Lacuna::DB::Building','body_id', mate => 'body'); __PACKAGE__->has_many('food_buildings','Lacuna::DB::Building::Food','body_id', mate => 'body'); @@ -103,6 +105,8 @@ __PACKAGE__->has_many('ore_buildings','Lacuna::DB::Building::Ore','body_id', mat __PACKAGE__->has_many('energy_buildings','Lacuna::DB::Building::Energy','body_id', mate => 'body'); __PACKAGE__->has_many('permanent_buildings','Lacuna::DB::Building::Permanent','body_id', mate => 'body'); + +# FREEBIES sub get_free_upgrade { my ($self, $class) = @_; return $self->freebies->{upgrades}{$class} || 0; @@ -722,6 +726,23 @@ sub recalc_stats { } } } + my $now = DateTime->now; + my $empire = $self->empire; + foreach my $resource (qw(energy water ore happiness)) { + my $boost = $resource.'_boost'; + if ($now < $empire->$boost) { + my $hour = $resource.'_hour'; + $stats{$hour} = sprintf '%.0f', $stats{$hour} * 1.25; + $stats{boost_enabled} = 1; + } + } + if ($now < $empire->food_boost) { + foreach my $type (FOOD_TYPES) { + my $method = $type.'_production_hour'; + $stats{$method} = sprintf '%.0f', $stats{$method} * 1.25; + $stats{boost_enabled} = 1; + } + } $self->update(\%stats); $self->put; return $self; @@ -791,6 +812,35 @@ sub tick { last; } } + + # check / clear boosts + if ($self->boost_enabled) { + my $empire = $self->empire; + my $still_enabled = 0; + foreach my $resource (qw(energy water ore happiness)) { + my $boost = $resource.'_boost'; + if ($now > $empire->$boost) { + my $hour = $resource.'_hour'; + $self->$hour(sprintf '%.0f', $self->$hour / 1.25); + } + else { + $still_enabled = 1; + } + } + if ($now > $empire->food_boost) { + foreach my $type (FOOD_TYPES) { + my $method = $type.'_production_hour'; + $self->$method(sprintf '%.0f', $self->$method / 1.25); + } + } + else { + $still_enabled = 1; + } + unless ($still_enabled) { + $self->boost_enabled(0); + } + } + $self->tick_to($now); # clear caches diff --git a/lib/Lacuna/Empire.pm b/lib/Lacuna/Empire.pm index e4921d31..06abeadf 100644 --- a/lib/Lacuna/Empire.pm +++ b/lib/Lacuna/Empire.pm @@ -6,6 +6,7 @@ use Lacuna::Util qw(cname format_date); use Lacuna::Map; use Lacuna::Verify; use Lacuna::Constants qw(MEDALS); +use DateTime; has simpledb => ( is => 'ro', @@ -170,7 +171,7 @@ sub set_status_message { my $empire = $self->get_empire_by_session($session_id); $empire->status_message($message); $empire->put; - return $self->get_status; + return $empire->get_status; } sub view_public_profile { @@ -204,8 +205,67 @@ sub view_public_profile { return { profile => \%out, status => $viewer_empire->get_status }; } +sub boost_ore { + my ($self, $session_id) = @_; + return $self->boost($session_id, 'ore_boost'); +} + +sub boost_water { + my ($self, $session_id) = @_; + return $self->boost($session_id, 'water_boost'); +} + +sub boost_energy { + my ($self, $session_id) = @_; + return $self->boost($session_id, 'energy_boost'); +} + +sub boost_food { + my ($self, $session_id) = @_; + return $self->boost($session_id, 'food_boost'); +} + +sub boost_happiness { + my ($self, $session_id) = @_; + return $self->boost($session_id, 'happiness_boost'); +} + +sub boost { + my ($self, $session_id, $type) = @_; + my $empire = $self->get_empire_by_session($session_id); + unless ($empire->essentia >= 5) { + confess [1011, 'Not enough essentia.']; + } + $empire->spend_essentia(5); + my $start = DateTime->now; + $start = $empire->$type if ($empire->$type > $start); + $start->add(days=>7); + $empire->$type($start); + $empire->trigger_full_update(skip_put=>1); + $empire->put; + return { + status => $empire->get_status, + $type => format_date($empire->$type), + }; +} + +sub view_boosts { + my ($self, $session_id) = @_; + my $empire = $self->get_empire_by_session($session_id); + return { + status => $empire->get_status, + boosts => { + food => format_date($empire->food_boost), + happiness => format_date($empire->happiness_boost), + water => format_date($empire->water_boost), + ore => format_date($empire->ore_boost), + energy => format_date($empire->energy_boost), + } + }; +} + -__PACKAGE__->register_rpc_method_names(qw(set_status_message find view_profile edit_profile view_public_profile is_name_available create found login logout get_full_status get_status)); +__PACKAGE__->register_rpc_method_names(qw(set_status_message find view_profile edit_profile view_public_profile is_name_available create found login logout get_full_status get_status boost_water boost_energy boost_ore boost_food boost_happiness view_boosts)); no Moose; -- 2.51.2 From 6959cf42ad622a1b32d3df251d168261db5e99b8 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Fri, 9 Apr 2010 17:09:04 -0500 Subject: [PATCH 09/12] added boosts --- t/Boosts.t | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 t/Boosts.t diff --git a/t/Boosts.t b/t/Boosts.t new file mode 100644 index 00000000..00a8a4b5 --- /dev/null +++ b/t/Boosts.t @@ -0,0 +1,40 @@ +use lib '../lib'; +use Test::More tests => 2; +use Test::Deep; +use Data::Dumper; +use 5.010; + +use TestHelper; +my $tester = TestHelper->new->generate_test_empire; +my $session_id = $tester->session->id; +my $empire = $tester->empire; +my $home = $empire->home_planet; +$empire->add_essentia(10)->put; + +my $base = $tester->post('empire','get_full_status', [$session_id]); +my $boost = $tester->post('empire','boost_ore', [$session_id]); +$empire = $tester->db->domain('empire')->find($empire->id); +$home->empire($empire); +my $building = Lacuna::DB::Building::Food::Farm::Malcud->new( + simpledb => $tester->db, + x => 0, + y => 1, + class => 'Lacuna::DB::Building::Food::Farm::Malcud', + date_created => DateTime->now, + body_id => $home->id, + body => $home, + empire_id => $empire->id, + empire => $empire, + level => 0, +); +$home->build_building($building); +$building->finish_upgrade; +my $boosts = $tester->post('empire','view_boosts', [$session_id]); +my $boosted = $tester->post('empire','get_full_status', [$session_id]); +cmp_ok($boosted->{result}{empire}{essentia}, '<', $base->{result}{empire}{essentia}, 'essentia spent'); +cmp_ok($boosted->{result}{empire}{planets}{$home->id}{ore_hour} - $building->ore_hour, '>', $base->{result}{empire}{planets}{$home->id}{ore_hour}, 'ore_hour increased'); + + +END { + $tester->cleanup; +} -- 2.51.2 From 0ef2e55356dde4acf4f5280a4d71eaeeb8cfd30c Mon Sep 17 00:00:00 2001 From: JT Smith Date: Fri, 9 Apr 2010 20:31:35 -0500 Subject: [PATCH 10/12] fixed dev ministry --- docs/Development.pod | 30 ++++++------------ lib/Lacuna/Building/Development.pm | 20 ++++++------ lib/Lacuna/DB/Building/Development.pm | 24 +++++++++++---- t/Development.t | 44 ++++++++++++++++++++++----- 4 files changed, 75 insertions(+), 43 deletions(-) diff --git a/docs/Development.pod b/docs/Development.pod index 5925c0a0..f181f880 100644 --- a/docs/Development.pod +++ b/docs/Development.pod @@ -19,36 +19,28 @@ This method is extended to include details about what's in your build queue. "name" : "Planetary Commmand", "to_level" : 9, "seconds_remaining" : 537, + "x" : 0, + "y" : 0 }, { "building_id" : "building-id-goes-here", "name" : "Wheat Farm", "to_level" : 15, "seconds_remaining" : 9748, + "x" : -1, + "y" : 4 } - ] + ], + "subsidy_cost" : 8 # the essentia cost to subsidize the build queue } -=head2 subsidize_build_queue ( session_id, building_id, amount ) +=head2 subsidize_build_queue ( session_id, building_id ) -Allows a player to speed up the build process, by spending essentia. Returns: +Allows a player to instantly finish any buildings in their build queue. The cost is returned by the C method. Returns: { "status" : { get_status() }, - "build_queue" : [ - { - "building_id" : "building-id-goes-here", - "name" : "Planetary Commmand", - "to_level" : 9, - "seconds_remaining" : 537, - }, - { - "building_id" : "building-id-goes-here", - "name" : "Wheat Farm", - "to_level" : 15, - "seconds_remaining" : 9748, - } - ] + "essentia_spent" : 8 } =head3 session_id @@ -58,9 +50,5 @@ A session id. =head3 building_id The id of the development ministry. - -=head3 amount - -The amount of essentia to spend. One essentia is worth 10 minutes of build time. =cut \ No newline at end of file diff --git a/lib/Lacuna/Building/Development.pm b/lib/Lacuna/Building/Development.pm index bca838a6..0bdc437d 100644 --- a/lib/Lacuna/Building/Development.pm +++ b/lib/Lacuna/Building/Development.pm @@ -17,23 +17,25 @@ around 'view' => sub { my $building = $empire->get_building($self->model_domain, $building_id); my $out = $orig->($self, $empire, $building); $out->{build_queue} = $building->format_build_queue; + $out->{subsidy_cost} = $building->calculate_subsidy; return $out; }; sub subsidize_build_queue { - my ($self, $session_id, $building_id, $amount) = @_; - if ($amount < 0) { - confess [1009, "You can't subsidize that little.", $amount]; - } + my ($self, $session_id, $building_id) = @_; my $empire = $self->get_empire_by_session($session_id); - if ($empire->essentia < $amount) { + my $building = $empire->get_building($self->model_class, $building_id); + my $subsidy = $building->calculate_subsidy; + if ($empire->essentia < $subsidy) { confess [1011, "You don't have enough essentia."]; } - my $building = $empire->get_building($self->model_class, $building_id); - $building->subsidize_build_queue($amount); + $empire->spend_essentia($subsidy); + $empire->trigger_full_update(skip_put=>1); + $empire->put; + $building->subsidize_build_queue; return { - build_queue => $building->format_build_queue, - status => $empire->get_status, + status => $empire->get_status, + essentia_spent => $subsidy, }; } diff --git a/lib/Lacuna/DB/Building/Development.pm b/lib/Lacuna/DB/Building/Development.pm index 720a5d65..aca7153c 100644 --- a/lib/Lacuna/DB/Building/Development.pm +++ b/lib/Lacuna/DB/Building/Development.pm @@ -4,15 +4,25 @@ use Moose; extends 'Lacuna::DB::Building'; sub subsidize_build_queue { - my ($self, $amount) = @_; + my ($self) = @_; + $self->body->tick; + my $builds = $self->simpledb->domain('build_queue')->search(where=>{body_id=>$self->body_id}); + while (my $build = $builds->next) { + $build->finish_build; + } +} + + +sub calculate_subsidy { + my ($self) = @_; + my $levels = 0; my $builds = $self->simpledb->domain('build_queue')->search(where=>{body_id=>$self->body_id}); while (my $build = $builds->next) { - $build->date_complete->subtract(seconds=>($amount * 600)); - $build->put; + $levels += $build->building->level; } - my $empire = $self->empire; - $empire->spend_essentia($amount); - $empire->trigger_full_update; + my $cost = int($levels / 3); + $cost = 1 if $cost < 1; + return $cost; } sub format_build_queue { @@ -26,6 +36,8 @@ sub format_build_queue { name => $target->name, to_level => ($target->level + 1), seconds_remaining => $build->seconds_remaining, + x => $target->x, + y => $target->y, }; } return \@queue; diff --git a/t/Development.t b/t/Development.t index 0db9488d..18207775 100644 --- a/t/Development.t +++ b/t/Development.t @@ -1,5 +1,5 @@ use lib '../lib'; -use Test::More tests => 1; +use Test::More tests => 2; use Test::Deep; use Data::Dumper; use 5.010; @@ -7,19 +7,49 @@ use 5.010; use TestHelper; my $tester = TestHelper->new->generate_test_empire; my $session_id = $tester->session->id; - +my $empire = $tester->empire; +my $home = $empire->home_planet; my $result; +$empire->add_essentia(10)->put; -my $command = $tester->empire->home_planet->command; -$command->level(5); -$command->put; +my $uni = Lacuna::DB::Building::University->new( + simpledb => $tester->db, + x => 0, + y => -1, + class => 'Lacuna::DB::Building::University', + date_created => DateTime->now, + body_id => $home->id, + body => $home, + empire_id => $empire->id, + empire => $empire, + level => 2, +); +$home->build_building($uni); +$uni->finish_upgrade; -$result = $tester->post('development', 'build', [$session_id, $tester->empire->home_planet_id, 3, 3]); +$home->ore_capacity(5000); +$home->energy_capacity(5000); +$home->food_capacity(5000); +$home->water_capacity(5000); +$home->bauxite_stored(5000); +$home->algae_stored(5000); +$home->energy_stored(5000); +$home->water_stored(5000); +$home->ore_hour(5000); +$home->energy_hour(5000); +$home->algae_production_hour(5000); +$home->water_hour(5000); +$home->put; -$result = $tester->post('development', 'view', [$session_id, $result->{result}{building}{id}]); +$result = $tester->post('development', 'build', [$session_id, $tester->empire->home_planet_id, 3, 3]); +my $id = $result->{result}{building}{id}; +$result = $tester->post('development', 'view', [$session_id, $id]); is($result->{result}{build_queue}[0]{name}, 'Development Ministry', "got build queue"); +$result = $tester->post('development', 'subsidize_build_queue', [$session_id, $id]); +ok($result->{result}{essentia_spent}, 'subsidy worked'); + END { $tester->cleanup; } -- 2.51.2 From 86d004ec277bec937fa53d6c77cac20e38787e68 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Fri, 9 Apr 2010 20:44:32 -0500 Subject: [PATCH 11/12] we have a company name --- bin/generate_docs.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/generate_docs.pl b/bin/generate_docs.pl index 5c7d5d80..891bbb70 100644 --- a/bin/generate_docs.pl +++ b/bin/generate_docs.pl @@ -23,7 +23,7 @@ foreach my $doc (@docs) { $parser->{perldoc_url_prefix} = '/api/'; $parser->{perldoc_url_postfix} = '.html'; $parser->{title_prefix} = 'The Lacuna Expanse API - '; - $parser->{html_footer} = '© 2010 lacunaexpanse.com'; + $parser->{html_footer} = '© 2010 Lacuna Expanse Corp'; open my $in, '<', $poddir.$doc; my $name = $doc; -- 2.51.2 From 0a3abd28f22f10518964022f5d5096e9a9c37918 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Fri, 9 Apr 2010 20:46:41 -0500 Subject: [PATCH 12/12] typo --- docs/Empire.pod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Empire.pod b/docs/Empire.pod index b3db0e6b..cfdfe093 100644 --- a/docs/Empire.pod +++ b/docs/Empire.pod @@ -340,7 +340,7 @@ A message to indicate what you're doing, how you're feeling, or other status ind -=head2 view_boost ( session_id ) +=head2 view_boosts ( session_id ) Shows the dates at which boosts have expired or will expire. Boosts are subsidies applied to various resources using essentia.