aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kmath.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/kmath.cpp')
-rw-r--r--engines/sci/engine/kmath.cpp64
1 files changed, 53 insertions, 11 deletions
diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp
index dbf317860f..f3769b653b 100644
--- a/engines/sci/engine/kmath.cpp
+++ b/engines/sci/engine/kmath.cpp
@@ -29,16 +29,40 @@
namespace Sci {
reg_t kRandom(EngineState *s, int argc, reg_t *argv) {
- int fromNumber = argv[0].toUint16();
- int toNumber = argv[1].toUint16();
- double randomNumber = fromNumber + ((toNumber + 1.0 - fromNumber) * (rand() / (RAND_MAX + 1.0)));
- return make_reg(0, (int)randomNumber);
+ switch (argc) {
+ case 1: // set seed to argv[0]
+ // SCI0/SCI01 just reset the seed to 0 instead of using argv[0] at all
+ return NULL_REG;
+
+ case 2: { // get random number
+ int fromNumber = argv[0].toUint16();
+ int toNumber = argv[1].toUint16();
+
+ // TODO/CHECKME: It is propbably not required to check whether
+ // toNumber is greater than fromNumber, at least not when one
+ // goes by their names, but let us be on the safe side and
+ // allow toNumber to be smaller than fromNumber too.
+ if (fromNumber > toNumber)
+ SWAP(fromNumber, toNumber);
+
+ const uint diff = (uint)(toNumber - fromNumber);
+
+ const int randomNumber = fromNumber + (int)g_sci->getRNG().getRandomNumber(diff);
+ return make_reg(0, randomNumber);
+ }
+
+ case 3: // get seed
+ // SCI0/01 did not support this at all
+ // Actually we would have to return the previous seed
+ error("kRandom: scripts asked for previous seed");
+ break;
+
+ default:
+ error("kRandom: unsupported argc");
+ }
}
reg_t kAbs(EngineState *s, int argc, reg_t *argv) {
- // This is a hack, but so is the code in Hoyle1 that needs it.
- if (argv[0].segment)
- return make_reg(0, 0x3e9); // Yes people, this is an object
return make_reg(0, abs(argv[0].toSint16()));
}
@@ -112,7 +136,7 @@ reg_t kCosDiv(EngineState *s, int argc, reg_t *argv) {
double cosval = cos(angle * PI / 180.0);
if ((cosval < 0.0001) && (cosval > -0.0001)) {
- warning("kCosDiv: Attempted division by zero");
+ error("kCosDiv: Attempted division by zero");
return SIGNAL_REG;
} else
return make_reg(0, (int16)(value / cosval));
@@ -124,7 +148,7 @@ reg_t kSinDiv(EngineState *s, int argc, reg_t *argv) {
double sinval = sin(angle * PI / 180.0);
if ((sinval < 0.0001) && (sinval > -0.0001)) {
- warning("kSinDiv: Attempted division by zero");
+ error("kSinDiv: Attempted division by zero");
return SIGNAL_REG;
} else
return make_reg(0, (int16)(value / sinval));
@@ -136,7 +160,7 @@ reg_t kTimesTan(EngineState *s, int argc, reg_t *argv) {
param -= 90;
if ((param % 90) == 0) {
- warning("kTimesTan: Attempted tan(pi/2)");
+ error("kTimesTan: Attempted tan(pi/2)");
return SIGNAL_REG;
} else
return make_reg(0, (int16) - (tan(param * PI / 180.0) * scale));
@@ -147,10 +171,28 @@ reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) {
int scale = (argc > 1) ? argv[1].toSint16() : 1;
if ((param % 90) == 0) {
- warning("kTimesCot: Attempted tan(pi/2)");
+ error("kTimesCot: Attempted tan(pi/2)");
return SIGNAL_REG;
} else
return make_reg(0, (int16)(tan(param * PI / 180.0) * scale));
}
+#ifdef ENABLE_SCI32
+
+reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) {
+ int16 multiplicant = argv[0].toSint16();
+ int16 multiplier = argv[1].toSint16();
+ int16 denominator = argv[2].toSint16();
+
+ // Sanity check...
+ if (!denominator) {
+ error("kMulDiv: attempt to divide by zero (%d * %d / %d", multiplicant, multiplier, denominator);
+ return NULL_REG;
+ }
+
+ return make_reg(0, multiplicant * multiplier / denominator);
+}
+
+#endif
+
} // End of namespace Sci