Resource provider regeneration
Implemented resource regeneration computation in the verse.compute_provider_regeneration() function. Created the PLANET_RES_REGEN update type, and added the corresponding implementation. Added resource regeneration constants registration.
This commit is contained in:
parent
d768766214
commit
66c72ef718
8 changed files with 443 additions and 1 deletions
|
@ -54,6 +54,14 @@ public class ConstantsRegistrarBean
|
|||
cDesc = "Initial universe size (offset relative to the centre).";
|
||||
defs.add( new ConstantDefinition( "game.universe.initialSize" , "Universe" , cDesc , 1.0 , 1.0 , true ) );
|
||||
|
||||
// Natural resources
|
||||
cDesc = "Global recovery rate multiplier for natural resources. This should be kept close to 0.";
|
||||
defs.add( new ConstantDefinition( "game.resources.recovery" , "Natural resources" , cDesc , 0.01 , 0.00001 ,
|
||||
1.0 ) );
|
||||
cDesc = "Resource recovery dampener. Lower means less dampening";
|
||||
defs.add( new ConstantDefinition( "game.resources.recoveryDampening" , "Natural resources" , cDesc , 1.5 , 1.0 ,
|
||||
true ) );
|
||||
|
||||
// Happiness
|
||||
String[] hcNames = {
|
||||
"noEmployment" , "employmentLimit" , "noDefence" , "defenceLimit" , "popPerDefencePoint" ,
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
\i parts/functions/110-prefs-functions.sql
|
||||
\i parts/functions/120-map-functions.sql
|
||||
\i parts/functions/140-planets-functions.sql
|
||||
\i parts/functions/145-resource-providers-functions.sql
|
||||
\i parts/functions/150-battle-functions.sql
|
||||
\i parts/functions/160-battle-views.sql
|
||||
\i parts/functions/163-alliance-functions.sql
|
||||
|
|
|
@ -19,4 +19,5 @@
|
|||
\i parts/updates/080-planet-construction.sql
|
||||
\i parts/updates/090-planet-military.sql
|
||||
\i parts/updates/100-planet-population.sql
|
||||
\i parts/updates/105-planet-resource-regeneration.sql
|
||||
\i parts/updates/110-planet-money.sql
|
||||
|
|
|
@ -28,19 +28,52 @@ CREATE TYPE log_type
|
|||
|
||||
-- Update types
|
||||
CREATE TYPE update_type AS ENUM (
|
||||
|
||||
/* Empires' money is being updated using the previous update's results */
|
||||
'EMPIRE_MONEY' ,
|
||||
|
||||
/* Empire research points are being attributed to technologies */
|
||||
'EMPIRE_RESEARCH' ,
|
||||
|
||||
/* The effects of empires' debts are being computed */
|
||||
'EMPIRE_DEBT' ,
|
||||
|
||||
/* Fleets which were 1 update away are arriving at their destination */
|
||||
'PLANET_FLEET_ARRIVALS' ,
|
||||
|
||||
/* Other fleets are moving */
|
||||
'PLANET_FLEET_MOVEMENTS' ,
|
||||
|
||||
/* Fleet states (e.g. "deploying", "unavailable", etc...) are being
|
||||
* updated.
|
||||
*/
|
||||
'PLANET_FLEET_STATUS' ,
|
||||
|
||||
/* Start new battles where necessary */
|
||||
'PLANET_BATTLE_START' ,
|
||||
|
||||
/* Process all in-progress battles */
|
||||
'PLANET_BATTLE_MAIN' ,
|
||||
|
||||
/* Finalise battles that need to be ended */
|
||||
'PLANET_BATTLE_END' ,
|
||||
|
||||
/* Abandon planets */
|
||||
'PLANET_ABANDON' ,
|
||||
|
||||
/* Handle civilian build queues */
|
||||
'PLANET_CONSTRUCTION' ,
|
||||
|
||||
/* Handle military build queues */
|
||||
'PLANET_MILITARY' ,
|
||||
|
||||
/* Update planets' population */
|
||||
'PLANET_POPULATION' ,
|
||||
|
||||
/* Regenerate resources in resource providers */
|
||||
'PLANET_RES_REGEN' ,
|
||||
|
||||
/* Compute income and upkeep of planets */
|
||||
'PLANET_MONEY'
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
-- LegacyWorlds Beta 6
|
||||
-- PostgreSQL database scripts
|
||||
--
|
||||
-- Resource providers functions
|
||||
--
|
||||
-- Copyright(C) 2004-2012, DeepClone Development
|
||||
-- --------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
* Compute resource provider regeneration
|
||||
*
|
||||
* This function computes the quantity in a resource provider after it has
|
||||
* been regenerated.
|
||||
*
|
||||
* Parameters:
|
||||
* _quantity The current quantity of resources in the provider
|
||||
* _max The maximal amount of resources supported by the
|
||||
* provider
|
||||
* _recovery_rate The provider's recovery rate
|
||||
*
|
||||
* Returns:
|
||||
* ? The new quantity of resources.
|
||||
*/
|
||||
CREATE OR REPLACE FUNCTION verse.compute_provider_regeneration(
|
||||
_quantity DOUBLE PRECISION ,
|
||||
_max DOUBLE PRECISION ,
|
||||
_recovery_rate DOUBLE PRECISION )
|
||||
RETURNS DOUBLE PRECISION
|
||||
STRICT IMMUTABLE
|
||||
SECURITY INVOKER
|
||||
AS $compute_provider_regeneration$
|
||||
|
||||
DECLARE
|
||||
_uc_recovery DOUBLE PRECISION;
|
||||
_uc_dampening DOUBLE PRECISION;
|
||||
_uc_ticks DOUBLE PRECISION;
|
||||
_result DOUBLE PRECISION;
|
||||
|
||||
BEGIN
|
||||
_uc_recovery := sys.get_constant( 'game.resources.recovery' );
|
||||
_uc_dampening := sys.get_constant( 'game.resources.recoveryDampening' );
|
||||
_uc_ticks := 1440; -- FIXME: this should be a constant
|
||||
|
||||
_result := ( 1 - _quantity / _max ) ^ _uc_dampening;
|
||||
_result := _quantity + _result * _recovery_rate * _uc_recovery / _uc_ticks;
|
||||
|
||||
IF _result > _max THEN
|
||||
_result := _max;
|
||||
END IF;
|
||||
|
||||
RETURN _result;
|
||||
END;
|
||||
$compute_provider_regeneration$ LANGUAGE PLPGSQL;
|
||||
|
||||
|
||||
REVOKE EXECUTE
|
||||
ON FUNCTION verse.compute_provider_regeneration(
|
||||
DOUBLE PRECISION , DOUBLE PRECISION ,
|
||||
DOUBLE PRECISION )
|
||||
FROM PUBLIC;
|
|
@ -0,0 +1,47 @@
|
|||
-- LegacyWorlds Beta 6
|
||||
-- PostgreSQL database scripts
|
||||
--
|
||||
-- Game updates - resource regeneration
|
||||
--
|
||||
-- Copyright(C) 2004-2012, DeepClone Development
|
||||
-- --------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
* Resource provider regeneration update
|
||||
*
|
||||
* This function computes the regeneration of resource providers for the current batch
|
||||
* of planets.
|
||||
*
|
||||
* Parameters:
|
||||
* _tick The identifier of the game update
|
||||
*/
|
||||
CREATE OR REPLACE FUNCTION sys.process_planet_res_regen_updates( _tick BIGINT )
|
||||
RETURNS VOID
|
||||
STRICT VOLATILE
|
||||
SECURITY INVOKER
|
||||
AS $process_planet_res_regen_updates$
|
||||
|
||||
UPDATE verse.resource_providers _provider
|
||||
|
||||
SET resprov_quantity = verse.compute_provider_regeneration(
|
||||
_provider.resprov_quantity ,
|
||||
_provider.resprov_quantity_max ,
|
||||
_provider.resprov_recovery
|
||||
)
|
||||
|
||||
FROM sys.updates _upd_sys
|
||||
INNER JOIN verse.updates _upd_verse
|
||||
ON _upd_verse.update_id = _upd_sys.id
|
||||
|
||||
WHERE _upd_sys.last_tick = $1
|
||||
AND _upd_sys.status = 'PROCESSING'
|
||||
AND _upd_sys.gu_type = 'PLANET_RES_REGEN'
|
||||
AND _provider.planet_id = _upd_verse.planet_id;
|
||||
|
||||
$process_planet_res_regen_updates$ LANGUAGE SQL;
|
||||
|
||||
|
||||
REVOKE EXECUTE
|
||||
ON FUNCTION sys.process_planet_res_regen_updates( BIGINT )
|
||||
FROM PUBLIC;
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Test the verse.compute_provider_regeneration() function
|
||||
*/
|
||||
BEGIN;
|
||||
|
||||
/* Define the necessary constants using default values */
|
||||
SELECT sys.uoc_constant( 'game.resources.recovery' , '(test)' , 'Resources' , 0.01 );
|
||||
SELECT sys.uoc_constant( 'game.resources.recoveryDampening' , '(test)' , 'Resources' , 1.5 );
|
||||
|
||||
/* Make sure the functions are not immutable during the tests */
|
||||
ALTER FUNCTION sys.get_constant( TEXT ) VOLATILE;
|
||||
ALTER FUNCTION verse.compute_provider_regeneration( DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ) VOLATILE;
|
||||
|
||||
/****** TESTS BEGIN HERE ******/
|
||||
SELECT plan( 6 );
|
||||
|
||||
|
||||
SELECT diag_test_name( 'verse.compute_provider_regeneration() - no regeneration at maximal quantity' );
|
||||
CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
|
||||
DECLARE
|
||||
rr DOUBLE PRECISION;
|
||||
BEGIN
|
||||
rr := 0.05;
|
||||
WHILE rr < 1
|
||||
LOOP
|
||||
IF verse.compute_provider_regeneration( 100.0 , 100.0 , rr ) > 100.0
|
||||
THEN
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
rr := rr + 0.05;
|
||||
END LOOP;
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
SELECT ok( _run_tests() );
|
||||
DROP FUNCTION _run_tests( );
|
||||
|
||||
|
||||
SELECT diag_test_name( 'verse.compute_provider_regeneration() - regeneration >= 0' );
|
||||
CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
|
||||
DECLARE
|
||||
qt DOUBLE PRECISION;
|
||||
rr DOUBLE PRECISION;
|
||||
BEGIN
|
||||
qt := 0;
|
||||
WHILE qt < 100.0
|
||||
LOOP
|
||||
rr := 0.05;
|
||||
WHILE rr < 1
|
||||
LOOP
|
||||
IF verse.compute_provider_regeneration( qt , 100.0 , rr ) <= qt
|
||||
THEN
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
rr := rr + 0.05;
|
||||
END LOOP;
|
||||
qt := qt + 5;
|
||||
END LOOP;
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
SELECT ok( _run_tests() );
|
||||
DROP FUNCTION _run_tests( );
|
||||
|
||||
|
||||
SELECT diag_test_name( 'verse.compute_provider_regeneration() - higher quantity => slower regeneration' );
|
||||
CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
|
||||
DECLARE
|
||||
pdiff DOUBLE PRECISION;
|
||||
diff DOUBLE PRECISION;
|
||||
qt DOUBLE PRECISION;
|
||||
rr DOUBLE PRECISION;
|
||||
BEGIN
|
||||
rr := 0.05;
|
||||
WHILE rr < 1
|
||||
LOOP
|
||||
qt := 0;
|
||||
WHILE qt < 100.0
|
||||
LOOP
|
||||
diff := verse.compute_provider_regeneration( qt , 100.0 , rr ) - qt;
|
||||
IF qt <> 0 AND diff >= pdiff
|
||||
THEN
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
pdiff := diff;
|
||||
qt := qt + 5;
|
||||
END LOOP;
|
||||
rr := rr + 0.05;
|
||||
END LOOP;
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
SELECT ok( _run_tests() );
|
||||
DROP FUNCTION _run_tests( );
|
||||
|
||||
|
||||
SELECT diag_test_name( 'verse.compute_provider_regeneration() - higher recovery rate => faster regeneration' );
|
||||
CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
|
||||
DECLARE
|
||||
pdiff DOUBLE PRECISION;
|
||||
diff DOUBLE PRECISION;
|
||||
qt DOUBLE PRECISION;
|
||||
rr DOUBLE PRECISION;
|
||||
BEGIN
|
||||
qt := 0;
|
||||
WHILE qt < 100.0
|
||||
LOOP
|
||||
rr := 0.05;
|
||||
WHILE rr < 1
|
||||
LOOP
|
||||
diff := verse.compute_provider_regeneration( qt , 100.0 , rr ) - qt;
|
||||
IF rr > 0.06 AND diff <= pdiff
|
||||
THEN
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
pdiff := diff;
|
||||
rr := rr + 0.05;
|
||||
END LOOP;
|
||||
qt := qt + 5;
|
||||
END LOOP;
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
SELECT ok( _run_tests() );
|
||||
DROP FUNCTION _run_tests( );
|
||||
|
||||
|
||||
SELECT diag_test_name( 'verse.compute_provider_regeneration() - effect of game.resources.recovery' );
|
||||
CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
|
||||
DECLARE
|
||||
pdiff DOUBLE PRECISION;
|
||||
diff DOUBLE PRECISION;
|
||||
qt DOUBLE PRECISION;
|
||||
rr DOUBLE PRECISION;
|
||||
BEGIN
|
||||
qt := 0;
|
||||
WHILE qt < 100.0
|
||||
LOOP
|
||||
rr := 0.01;
|
||||
WHILE rr < 1
|
||||
LOOP
|
||||
UPDATE sys.constant_definitions
|
||||
SET c_value = rr
|
||||
WHERE name = 'game.resources.recovery';
|
||||
diff := verse.compute_provider_regeneration( qt , 100.0 , 0.5 ) - qt;
|
||||
IF rr > 0.011 AND diff <= pdiff
|
||||
THEN
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
pdiff := diff;
|
||||
rr := rr + 0.01;
|
||||
END LOOP;
|
||||
qt := qt + 5;
|
||||
END LOOP;
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
SELECT ok( _run_tests() );
|
||||
DROP FUNCTION _run_tests( );
|
||||
UPDATE sys.constant_definitions
|
||||
SET c_value = 0.01
|
||||
WHERE name = 'game.resources.recovery';
|
||||
|
||||
|
||||
|
||||
SELECT diag_test_name( 'verse.compute_provider_regeneration() - effect of game.resources.recoveryDampening' );
|
||||
CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
|
||||
DECLARE
|
||||
pdiff DOUBLE PRECISION;
|
||||
diff DOUBLE PRECISION;
|
||||
qt DOUBLE PRECISION;
|
||||
rrd DOUBLE PRECISION;
|
||||
BEGIN
|
||||
qt := 5;
|
||||
WHILE qt < 100.0
|
||||
LOOP
|
||||
rrd := 1;
|
||||
WHILE rrd < 3
|
||||
LOOP
|
||||
UPDATE sys.constant_definitions
|
||||
SET c_value = rrd
|
||||
WHERE name = 'game.resources.recoveryDampening';
|
||||
diff := verse.compute_provider_regeneration( qt , 100.0 , 0.5 ) - qt;
|
||||
IF rrd > 1.01 AND diff >= pdiff
|
||||
THEN
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
pdiff := diff;
|
||||
rrd := rrd + 0.25;
|
||||
END LOOP;
|
||||
qt := qt + 5;
|
||||
END LOOP;
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$ LANGUAGE PLPGSQL;
|
||||
SELECT ok( _run_tests() );
|
||||
DROP FUNCTION _run_tests( );
|
||||
UPDATE sys.constant_definitions
|
||||
SET c_value = 1.5
|
||||
WHERE name = 'game.resources.recoveryDampening';
|
||||
|
||||
|
||||
SELECT * FROM finish( );
|
||||
ROLLBACK;
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Test for the sys.process_planet_res_regen_updates() function
|
||||
*/
|
||||
BEGIN;
|
||||
|
||||
/* We need to create a natural resource and a pair of planets */
|
||||
\i utils/strings.sql
|
||||
\i utils/resources.sql
|
||||
\i utils/accounts.sql
|
||||
\i utils/naming.sql
|
||||
\i utils/universe.sql
|
||||
SELECT _create_natural_resources( 1 , 'testResource' );
|
||||
SELECT _create_raw_planets( 3 , 'testPlanet' );
|
||||
|
||||
/* Define the necessary constants using default values */
|
||||
SELECT sys.uoc_constant( 'game.resources.recovery' , '(test)' , 'Resources' , 0.01 );
|
||||
SELECT sys.uoc_constant( 'game.resources.recoveryDampening' , '(test)' , 'Resources' , 1.5 );
|
||||
|
||||
/* Create resource providers */
|
||||
INSERT INTO verse.resource_providers ( planet_id , resource_name_id ,
|
||||
resprov_quantity_max , resprov_quantity ,
|
||||
resprov_difficulty , resprov_recovery )
|
||||
VALUES (
|
||||
_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
|
||||
100 , 50 ,
|
||||
0.5 , 0.5
|
||||
) , (
|
||||
_get_map_name( 'testPlanet2' ) , _get_string( 'testResource1' ) ,
|
||||
100 , 100 ,
|
||||
0.5 , 0.5
|
||||
) , (
|
||||
_get_map_name( 'testPlanet3' ) , _get_string( 'testResource1' ) ,
|
||||
100 , 50 ,
|
||||
0.5 , 0.5
|
||||
);
|
||||
|
||||
/* Insert update records for the planets. Planets 1 and 2 will be processed,
|
||||
* planet testPlanet3 will not.
|
||||
*/
|
||||
INSERT INTO sys.updates ( id , gu_type , status , last_tick )
|
||||
VALUES ( 1 , 'PLANET_RES_REGEN' , 'PROCESSING' , 0 );
|
||||
INSERT INTO verse.updates ( update_id , planet_id )
|
||||
VALUES ( 1 , _get_map_name( 'testPlanet1' ) );
|
||||
|
||||
INSERT INTO sys.updates ( id , gu_type , status , last_tick )
|
||||
VALUES ( 2 , 'PLANET_RES_REGEN' , 'PROCESSING' , 0 );
|
||||
INSERT INTO verse.updates ( update_id , planet_id )
|
||||
VALUES ( 2 , _get_map_name( 'testPlanet2' ) );
|
||||
|
||||
INSERT INTO sys.updates ( id , gu_type , status , last_tick )
|
||||
VALUES ( 3 , 'PLANET_RES_REGEN' , 'PROCESSED' , 0 );
|
||||
INSERT INTO verse.updates ( update_id , planet_id )
|
||||
VALUES ( 3 , _get_map_name( 'testPlanet3' ) );
|
||||
|
||||
/* Helper function that gets a provider's current quantity */
|
||||
CREATE FUNCTION _get_quantity( _planet TEXT )
|
||||
RETURNS DOUBLE PRECISION
|
||||
AS $$
|
||||
SELECT resprov_quantity FROM verse.resource_providers
|
||||
WHERE planet_id = _get_map_name( $1 )
|
||||
AND resource_name_id = _get_string( 'testResource1' );
|
||||
$$ LANGUAGE SQL;
|
||||
|
||||
/****** TESTS BEGIN HERE ******/
|
||||
SELECT plan( 6 );
|
||||
|
||||
|
||||
SELECT sys.process_planet_res_regen_updates( 10 );
|
||||
SELECT diag_test_name( 'PLANET_RES_REGEN update - Wrong update identifier (1/3)' );
|
||||
SELECT ok( _get_quantity( 'testPlanet1' ) = 50 );
|
||||
SELECT diag_test_name( 'PLANET_RES_REGEN update - Wrong update identifier (2/3)' );
|
||||
SELECT ok( _get_quantity( 'testPlanet2' ) = 100 );
|
||||
SELECT diag_test_name( 'PLANET_RES_REGEN update - Wrong update identifier (3/3)' );
|
||||
SELECT ok( _get_quantity( 'testPlanet3' ) = 50 );
|
||||
|
||||
|
||||
SELECT sys.process_planet_res_regen_updates( 0 );
|
||||
SELECT diag_test_name( 'PLANET_RES_REGEN update - Processed planet with quantity < max.' );
|
||||
SELECT ok( _get_quantity( 'testPlanet1' ) > 50 );
|
||||
SELECT diag_test_name( 'PLANET_RES_REGEN update - Processed planet with quantity = max.' );
|
||||
SELECT ok( _get_quantity( 'testPlanet2' ) = 100 );
|
||||
SELECT diag_test_name( 'PLANET_RES_REGEN update - Already processed planet' );
|
||||
SELECT ok( _get_quantity( 'testPlanet3' ) = 50 );
|
||||
|
||||
|
||||
SELECT * FROM finish( );
|
||||
ROLLBACK;
|
Reference in a new issue