1 /************************************************************************
2  *                                                                      *
3  *  FreeSynd - a remake of the classic Bullfrog game "Syndicate".       *
4  *                                                                      *
5  *   Copyright (C) 2012  Ryan Cocks <ryan@ryancocks.net>                *
6  *                                                                      *
7  *    This program is free software;  you can redistribute it and / or  *
8  *  modify it  under the  terms of the  GNU General  Public License as  *
9  *  published by the Free Software Foundation; either version 2 of the  *
10  *  License, or (at your option) any later version.                     *
11  *                                                                      *
12  *    This program is  distributed in the hope that it will be useful,  *
13  *  but WITHOUT  ANY WARRANTY;  without even  the implied  warranty of  *
14  *  MERCHANTABILITY  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  *
15  *  General Public License for more details.                            *
16  *                                                                      *
17  *    You can view the GNU  General Public License, online, at the GNU  *
18  *  project's  web  site;  see <http://www.gnu.org/licenses/gpl.html>.  *
19  *  The full text of the license is also included in the file COPYING.  *
20  *                                                                      *
21  ************************************************************************/
22 
23 #include "ipastim.h"
24 #include <assert.h>
25 
26 #ifdef _DEBUG
27 #include <stdio.h>
28 
29 const char * IPAStim::IPANames[3] = {
30     "Adrenaline",
31     "Perception",
32     "Intelligence"
33 };
34 #endif
35 
IPAStim(IPAType ipa_type,int amount,int dependency)36 IPAStim::IPAStim(IPAType ipa_type, int amount, int dependency)
37 :ipa_type_(ipa_type), effect_(50), effect_timer_(1000), dependency_timer_(4500)
38 {
39     assert(ipa_type_ <= 3);
40     setLevels(amount, dependency);
41 }
42 
getMagnitude() const43 int IPAStim::getMagnitude() const
44 {
45     return dependency_ < amount_ ? amount_ - dependency_: dependency_ - amount_;
46 }
47 
48 
getMultiplier() const49 float IPAStim::getMultiplier() const
50 {
51     // With an agent with no mods and his adrenaline dependency in the
52     // center: his speed will be halved or doubled with the adrenaline
53     // bar at the respective extreme.
54 
55     // An agent with no adrenaline, no mods and no weaponry walks at
56     // the same speed as a civilian.
57 
58     // This function has been implemented to assume that FULL adrenaline
59     // would give a 2x increase in speed and the worst case would leave
60     // you walking at a half speed. With neutral adrenaline it has no
61     // effect and therefore returns 1.
62 
63     // Thus, the algortithm used here goes from 0.5 to 1 for 'negative'
64     // adrenaline and 1 to 2 on the positive side.
65     int magnitude = getMagnitude();
66 
67     if(direction() == IPA_boost) {
68         // return value is 1 to 2 for values
69         // of 'magnitude' from 0 to 100
70         // If you fiddle with this equation beware of
71         // values for effective which are close to 0
72         float mult = part_of_two(magnitude);
73         assert(mult >= 1 && mult <= 2);
74         //printf("%s boost: m:%d->%fx\n", getName(), magnitude_, mult);
75         return mult;
76     } else {
77         // < 0
78         // range: 0.5 up towards 1
79         float mult = 1.0/part_of_two(magnitude);
80         assert(mult >= 0.5 && mult <= 1.0);
81         //printf("%s reduce: m:%d->%fx\n", getName(), magnitude_, mult);
82         return mult;
83     }
84 }
85 
setLevels(int amount,int dependency,int effect)86 void IPAStim::setLevels(int amount, int dependency, int effect)
87 {
88     amount_ = amount;
89     dependency_ = dependency;
90 
91     effect_ = dependency;
92 
93     //printf("%s: A: %d, D: %d, E: %d\n", getName(), amount, dependency, effect_);
94 }
95 
processTicks(int elapsed)96 void IPAStim::processTicks(int elapsed)
97 {
98     // From observation of the original Syndicate:
99     // * Effect moves about once a second.
100     // * Dependency bar moves once for every 5 or 6 moves of Effect
101     // * Effect is independent of amount! If you flick amount to the
102     //   other side effect will stay where it was.
103     // * there appear to be 50 'positions' on the bar so it looks
104     //   like the levels move in notches, 1% at a time.
105 
106     if(effect_timer_.update(elapsed))
107     {
108         if(effect_ > amount_)
109         {
110             --effect_;
111         }
112         else if(effect_ < amount_)
113         {
114             ++effect_;
115         }
116         else // equal
117         {
118             // So once effect has 'caught up' to amount then they
119             // both start moving towards the value of dependency
120             // together
121             if(amount_ > dependency_)
122             {
123                 effect_ = --amount_;
124             }
125             else if(amount_ < dependency_)
126             {
127                 effect_ = ++amount_;
128             }
129         }
130         assert(effect_ >= 0 && effect_ <= 100);
131     }
132 
133     // The dependency indicator always creaps towards amount
134     if(dependency_timer_.update(elapsed))
135     {
136         if (dependency_ > amount_) {
137             --dependency_;
138         } else if (dependency_ < amount_) {
139             ++dependency_;
140         } else {
141             // equal
142             if (amount_ < 50) {
143                 ++amount_;
144                 ++dependency_;
145             } else if (amount_ > 50) {
146                 --amount_;
147                 --dependency_;
148             }
149         }
150         assert(dependency_ >= 0 && dependency_ <= 100);
151 
152     }
153 }
154