Browse Source

🎨 Fix line endings

pull/1894/head
Anders Jenbo 5 years ago
parent
commit
c11945e62b
  1. 4
      Source/control.h
  2. 308
      Source/engine/animationinfo.cpp
  3. 202
      Source/engine/animationinfo.h
  4. 10
      Source/storm/storm_dvlnet.h
  5. 146
      Source/utils/math.h
  6. 38
      Source/utils/stdcompat/string_view.hpp
  7. 1048
      test/animationinfo_test.cpp
  8. 62
      test/appfat_test.cpp
  9. 254
      test/automap_test.cpp
  10. 30
      test/codec_test.cpp
  11. 58
      test/control_test.cpp
  12. 38
      test/cursor_test.cpp
  13. 38
      test/dead_test.cpp
  14. 28
      test/diablo_test.cpp
  15. 34
      test/doom_test.cpp
  16. 42
      test/drlg_l1_test.cpp
  17. 24
      test/drlg_l2_test.cpp
  18. 70
      test/drlg_l3_test.cpp
  19. 42
      test/drlg_l4_test.cpp
  20. 112
      test/effects_test.cpp
  21. 452
      test/inv_test.cpp
  22. 76
      test/lighting_test.cpp
  23. 174
      test/missiles_test.cpp
  24. 1212
      test/pack_test.cpp
  25. 166
      test/player_test.cpp
  26. 328
      test/scrollrt_test.cpp
  27. 148
      test/stores_test.cpp

4
Source/control.h

@ -68,8 +68,8 @@ extern int initialDropGoldValue;
extern bool panbtndown; extern bool panbtndown;
extern bool spselflag; extern bool spselflag;
/** /**
* @brief Check if the UI can cover the game area entierly * @brief Check if the UI can cover the game area entierly
*/ */
inline bool CanPanelsCoverView() inline bool CanPanelsCoverView()
{ {

308
Source/engine/animationinfo.cpp

@ -1,154 +1,154 @@
/** /**
* @file animationinfo.cpp * @file animationinfo.cpp
* *
* Contains the core animation information and related logic * Contains the core animation information and related logic
*/ */
#include "animationinfo.h" #include "animationinfo.h"
#include "appfat.h" #include "appfat.h"
#include "nthread.h" #include "nthread.h"
#include "utils/log.hpp" #include "utils/log.hpp"
namespace devilution { namespace devilution {
int AnimationInfo::GetFrameToUseForRendering() const int AnimationInfo::GetFrameToUseForRendering() const
{ {
// Normal logic is used, // Normal logic is used,
// - if no frame-skipping is required and so we have exactly one Animationframe per game tick // - if no frame-skipping is required and so we have exactly one Animationframe per game tick
// or // or
// - if we load from a savegame where the new variables are not stored (we don't want to break savegame compatiblity because of smoother rendering of one animation) // - if we load from a savegame where the new variables are not stored (we don't want to break savegame compatiblity because of smoother rendering of one animation)
if (RelevantFramesForDistributing <= 0) if (RelevantFramesForDistributing <= 0)
return CurrentFrame; return CurrentFrame;
if (CurrentFrame > RelevantFramesForDistributing) if (CurrentFrame > RelevantFramesForDistributing)
return CurrentFrame; return CurrentFrame;
assert(TicksSinceSequenceStarted >= 0); assert(TicksSinceSequenceStarted >= 0);
// we don't use the processed game ticks alone but also the fragtion of the next game tick (if a rendering happens between game ticks). This helps to smooth the animations. // we don't use the processed game ticks alone but also the fragtion of the next game tick (if a rendering happens between game ticks). This helps to smooth the animations.
float totalTicksForCurrentAnimationSequence = gfProgressToNextGameTick + (float)TicksSinceSequenceStarted; float totalTicksForCurrentAnimationSequence = gfProgressToNextGameTick + (float)TicksSinceSequenceStarted;
// 1 added for rounding reasons. float to int cast always truncate. // 1 added for rounding reasons. float to int cast always truncate.
int absoluteAnimationFrame = 1 + (int)(totalTicksForCurrentAnimationSequence * TickModifier); int absoluteAnimationFrame = 1 + (int)(totalTicksForCurrentAnimationSequence * TickModifier);
if (SkippedFramesFromPreviousAnimation > 0) { if (SkippedFramesFromPreviousAnimation > 0) {
// absoluteAnimationFrames contains also the Frames from the previous Animation, so if we want to get the current Frame we have to remove them // absoluteAnimationFrames contains also the Frames from the previous Animation, so if we want to get the current Frame we have to remove them
absoluteAnimationFrame -= SkippedFramesFromPreviousAnimation; absoluteAnimationFrame -= SkippedFramesFromPreviousAnimation;
if (absoluteAnimationFrame <= 0) { if (absoluteAnimationFrame <= 0) {
// We still display the remains of the previous Animation // We still display the remains of the previous Animation
absoluteAnimationFrame = NumberOfFrames + absoluteAnimationFrame; absoluteAnimationFrame = NumberOfFrames + absoluteAnimationFrame;
} }
} else if (absoluteAnimationFrame > RelevantFramesForDistributing) { } else if (absoluteAnimationFrame > RelevantFramesForDistributing) {
// this can happen if we are at the last frame and the next game tick is due (gfProgressToNextGameTick >= 1.0f) // this can happen if we are at the last frame and the next game tick is due (gfProgressToNextGameTick >= 1.0f)
if (absoluteAnimationFrame > (RelevantFramesForDistributing + 1)) { if (absoluteAnimationFrame > (RelevantFramesForDistributing + 1)) {
// we should never have +2 frames even if next game tick is due // we should never have +2 frames even if next game tick is due
Log("GetFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {} MaxFrame {})", absoluteAnimationFrame, RelevantFramesForDistributing); Log("GetFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {} MaxFrame {})", absoluteAnimationFrame, RelevantFramesForDistributing);
} }
return RelevantFramesForDistributing; return RelevantFramesForDistributing;
} }
if (absoluteAnimationFrame <= 0) { if (absoluteAnimationFrame <= 0) {
Log("GetFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {})", absoluteAnimationFrame); Log("GetFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {})", absoluteAnimationFrame);
return 1; return 1;
} }
return absoluteAnimationFrame; return absoluteAnimationFrame;
} }
void AnimationInfo::SetNewAnimation(byte *pData, int numberOfFrames, int delayLen, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/) void AnimationInfo::SetNewAnimation(byte *pData, int numberOfFrames, int delayLen, AnimationDistributionFlags flags /*= AnimationDistributionFlags::None*/, int numSkippedFrames /*= 0*/, int distributeFramesBeforeFrame /*= 0*/)
{ {
if ((flags & AnimationDistributionFlags::RepeatedAction) == AnimationDistributionFlags::RepeatedAction && distributeFramesBeforeFrame != 0 && NumberOfFrames == numberOfFrames && CurrentFrame >= distributeFramesBeforeFrame && CurrentFrame != NumberOfFrames) { if ((flags & AnimationDistributionFlags::RepeatedAction) == AnimationDistributionFlags::RepeatedAction && distributeFramesBeforeFrame != 0 && NumberOfFrames == numberOfFrames && CurrentFrame >= distributeFramesBeforeFrame && CurrentFrame != NumberOfFrames) {
// We showed the same Animation (for example a melee attack) before but truncated the Animation. // We showed the same Animation (for example a melee attack) before but truncated the Animation.
// So now we should add them back to the new Animation. This increases the speed of the current Animation but the game logic/ticks isn't affected. // So now we should add them back to the new Animation. This increases the speed of the current Animation but the game logic/ticks isn't affected.
SkippedFramesFromPreviousAnimation = NumberOfFrames - CurrentFrame; SkippedFramesFromPreviousAnimation = NumberOfFrames - CurrentFrame;
} else { } else {
SkippedFramesFromPreviousAnimation = 0; SkippedFramesFromPreviousAnimation = 0;
} }
this->pData = pData; this->pData = pData;
NumberOfFrames = numberOfFrames; NumberOfFrames = numberOfFrames;
CurrentFrame = 1; CurrentFrame = 1;
DelayCounter = 0; DelayCounter = 0;
DelayLen = delayLen; DelayLen = delayLen;
TicksSinceSequenceStarted = 0; TicksSinceSequenceStarted = 0;
RelevantFramesForDistributing = 0; RelevantFramesForDistributing = 0;
TickModifier = 0.0f; TickModifier = 0.0f;
if (numSkippedFrames != 0 || flags != AnimationDistributionFlags::None) { if (numSkippedFrames != 0 || flags != AnimationDistributionFlags::None) {
// Animation Frames that will be adjusted for the skipped Frames/game ticks // Animation Frames that will be adjusted for the skipped Frames/game ticks
int relevantAnimationFramesForDistributing = numberOfFrames; int relevantAnimationFramesForDistributing = numberOfFrames;
if (distributeFramesBeforeFrame != 0) { if (distributeFramesBeforeFrame != 0) {
// After an attack hits (_pAFNum or _pSFNum) it can be canceled or another attack can be queued and this means the animation is canceled. // After an attack hits (_pAFNum or _pSFNum) it can be canceled or another attack can be queued and this means the animation is canceled.
// In normal attacks frame skipping always happens before the attack actual hit. // In normal attacks frame skipping always happens before the attack actual hit.
// This has the advantage that the sword or bow always points to the enemy when the hit happens (_pAFNum or _pSFNum). // This has the advantage that the sword or bow always points to the enemy when the hit happens (_pAFNum or _pSFNum).
// Our distribution logic must also regard this behaviour, so we are not allowed to distribute the skipped animations after the actual hit (_pAnimStopDistributingAfterFrame). // Our distribution logic must also regard this behaviour, so we are not allowed to distribute the skipped animations after the actual hit (_pAnimStopDistributingAfterFrame).
relevantAnimationFramesForDistributing = distributeFramesBeforeFrame - 1; relevantAnimationFramesForDistributing = distributeFramesBeforeFrame - 1;
} }
// How many game ticks are needed to advance one Animation Frame // How many game ticks are needed to advance one Animation Frame
int ticksPerFrame = (delayLen + 1); int ticksPerFrame = (delayLen + 1);
// Game ticks that will be adjusted for the skipped Frames/game ticks // Game ticks that will be adjusted for the skipped Frames/game ticks
int relevantAnimationTicksForDistribution = relevantAnimationFramesForDistributing * ticksPerFrame; int relevantAnimationTicksForDistribution = relevantAnimationFramesForDistributing * ticksPerFrame;
// How many game ticks will the Animation be really shown (skipped Frames and game ticks removed) // How many game ticks will the Animation be really shown (skipped Frames and game ticks removed)
int relevantAnimationTicksWithSkipping = relevantAnimationTicksForDistribution - (numSkippedFrames * ticksPerFrame); int relevantAnimationTicksWithSkipping = relevantAnimationTicksForDistribution - (numSkippedFrames * ticksPerFrame);
if ((flags & AnimationDistributionFlags::ProcessAnimationPending) == AnimationDistributionFlags::ProcessAnimationPending) { if ((flags & AnimationDistributionFlags::ProcessAnimationPending) == AnimationDistributionFlags::ProcessAnimationPending) {
// If ProcessAnimation will be called after SetNewAnimation (in same game tick as SetNewAnimation), we increment the Animation-Counter. // If ProcessAnimation will be called after SetNewAnimation (in same game tick as SetNewAnimation), we increment the Animation-Counter.
// If no delay is specified, this will result in complete skipped frame (see ProcessAnimation). // If no delay is specified, this will result in complete skipped frame (see ProcessAnimation).
// But if we have a delay specified, this would only result in a reduced time the first frame is shown (one skipped delay). // But if we have a delay specified, this would only result in a reduced time the first frame is shown (one skipped delay).
// Because of that, we only the remove one game tick from the time the Animation is shown // Because of that, we only the remove one game tick from the time the Animation is shown
relevantAnimationTicksWithSkipping -= 1; relevantAnimationTicksWithSkipping -= 1;
// The Animation Distribution Logic needs to account how many game ticks passed since the Animation started. // The Animation Distribution Logic needs to account how many game ticks passed since the Animation started.
// Because ProcessAnimation will increase this later (in same game tick as SetNewAnimation), we correct this upfront. // Because ProcessAnimation will increase this later (in same game tick as SetNewAnimation), we correct this upfront.
// This also means Rendering should never hapen with TicksSinceSequenceStarted < 0. // This also means Rendering should never hapen with TicksSinceSequenceStarted < 0.
TicksSinceSequenceStarted = -1; TicksSinceSequenceStarted = -1;
} }
if ((flags & AnimationDistributionFlags::SkipsDelayOfLastFrame) == AnimationDistributionFlags::SkipsDelayOfLastFrame) { if ((flags & AnimationDistributionFlags::SkipsDelayOfLastFrame) == AnimationDistributionFlags::SkipsDelayOfLastFrame) {
// The logic for player/monster/... (not ProcessAnimation) only checks the frame not the delay. // The logic for player/monster/... (not ProcessAnimation) only checks the frame not the delay.
// That means if a delay is specified, the last-frame is shown less then the other frames // That means if a delay is specified, the last-frame is shown less then the other frames
// Example: // Example:
// If we have a animation with 3 frames and with a delay of 1 (ticksPerFrame = 2). // If we have a animation with 3 frames and with a delay of 1 (ticksPerFrame = 2).
// The logic checks "if (frame == 3) { start_new_animation(); }" // The logic checks "if (frame == 3) { start_new_animation(); }"
// This will result that frame 4 is the last shown Animation Frame. // This will result that frame 4 is the last shown Animation Frame.
// GameTick Frame Cnt // GameTick Frame Cnt
// 1 1 0 // 1 1 0
// 2 1 1 // 2 1 1
// 3 2 0 // 3 2 0
// 3 2 1 // 3 2 1
// 4 3 0 // 4 3 0
// 5 - - // 5 - -
// in game tick 5 ProcessPlayer sees Frame = 3 and stops the animation. // in game tick 5 ProcessPlayer sees Frame = 3 and stops the animation.
// But Frame 3 is only shown 1 game tick and all other Frames are shown 2 game ticks. // But Frame 3 is only shown 1 game tick and all other Frames are shown 2 game ticks.
// Thats why we need to remove the Delay of the last Frame from the time (game ticks) the Animation is shown // Thats why we need to remove the Delay of the last Frame from the time (game ticks) the Animation is shown
relevantAnimationTicksWithSkipping -= delayLen; relevantAnimationTicksWithSkipping -= delayLen;
} }
// The truncated Frames from previous Animation will also be shown, so we also have to distribute them for the given time (game ticks) // The truncated Frames from previous Animation will also be shown, so we also have to distribute them for the given time (game ticks)
relevantAnimationTicksForDistribution += (SkippedFramesFromPreviousAnimation * ticksPerFrame); relevantAnimationTicksForDistribution += (SkippedFramesFromPreviousAnimation * ticksPerFrame);
// if we skipped Frames we need to expand the game ticks to make one game tick for this Animation "faster" // if we skipped Frames we need to expand the game ticks to make one game tick for this Animation "faster"
float tickModifier = (float)relevantAnimationTicksForDistribution / (float)relevantAnimationTicksWithSkipping; float tickModifier = (float)relevantAnimationTicksForDistribution / (float)relevantAnimationTicksWithSkipping;
// tickModifier specifies the Animation fraction per game tick, so we have to remove the delay from the variable // tickModifier specifies the Animation fraction per game tick, so we have to remove the delay from the variable
tickModifier /= ticksPerFrame; tickModifier /= ticksPerFrame;
RelevantFramesForDistributing = relevantAnimationFramesForDistributing; RelevantFramesForDistributing = relevantAnimationFramesForDistributing;
TickModifier = tickModifier; TickModifier = tickModifier;
} }
} }
void AnimationInfo::ProcessAnimation() void AnimationInfo::ProcessAnimation()
{ {
DelayCounter++; DelayCounter++;
TicksSinceSequenceStarted++; TicksSinceSequenceStarted++;
if (DelayCounter > DelayLen) { if (DelayCounter > DelayLen) {
DelayCounter = 0; DelayCounter = 0;
CurrentFrame++; CurrentFrame++;
if (CurrentFrame > NumberOfFrames) { if (CurrentFrame > NumberOfFrames) {
CurrentFrame = 1; CurrentFrame = 1;
TicksSinceSequenceStarted = 0; TicksSinceSequenceStarted = 0;
} }
} }
} }
} // namespace devilution } // namespace devilution

202
Source/engine/animationinfo.h

@ -1,101 +1,101 @@
/** /**
* @file animationinfo.h * @file animationinfo.h
* *
* Contains the core animation information and related logic * Contains the core animation information and related logic
*/ */
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <type_traits> #include <type_traits>
#include "engine.h" #include "engine.h"
namespace devilution { namespace devilution {
/** /**
* @brief Specifies what special logics are applied for a Animation * @brief Specifies what special logics are applied for a Animation
*/ */
enum AnimationDistributionFlags : uint8_t { enum AnimationDistributionFlags : uint8_t {
None = 0, None = 0,
/** /**
* @brief ProcessAnimation will be called after SetNewAnimation (in same game tick as NewPlrAnim) * @brief ProcessAnimation will be called after SetNewAnimation (in same game tick as NewPlrAnim)
*/ */
ProcessAnimationPending = 1 << 0, ProcessAnimationPending = 1 << 0,
/** /**
* @brief Delay of last Frame is ignored (for example, because only Frame and not delay is checked in game_logic) * @brief Delay of last Frame is ignored (for example, because only Frame and not delay is checked in game_logic)
*/ */
SkipsDelayOfLastFrame = 1 << 1, SkipsDelayOfLastFrame = 1 << 1,
/** /**
* @brief Repeated Animation (for example same player melee attack, that can be repeated directly after hit frame and doesn't need to show all animation frames) * @brief Repeated Animation (for example same player melee attack, that can be repeated directly after hit frame and doesn't need to show all animation frames)
*/ */
RepeatedAction = 1 << 2, RepeatedAction = 1 << 2,
}; };
/* /*
* @brief Contains the core animation information and related logic * @brief Contains the core animation information and related logic
*/ */
class AnimationInfo { class AnimationInfo {
public: public:
/** /**
* @brief Pointer to Animation Data * @brief Pointer to Animation Data
*/ */
byte *pData; byte *pData;
/** /**
* @brief Additional delay of each animation in the current animation * @brief Additional delay of each animation in the current animation
*/ */
int DelayLen; int DelayLen;
/** /**
* @brief Increases by one each game tick, counting how close we are to DelayLen * @brief Increases by one each game tick, counting how close we are to DelayLen
*/ */
int DelayCounter; int DelayCounter;
/** /**
* @brief Number of frames in current animation * @brief Number of frames in current animation
*/ */
int NumberOfFrames; int NumberOfFrames;
/** /**
* @brief Current frame of animation * @brief Current frame of animation
*/ */
int CurrentFrame; int CurrentFrame;
/** /**
* @brief Calculates the Frame to use for the Animation rendering * @brief Calculates the Frame to use for the Animation rendering
* @return The Frame to use for rendering * @return The Frame to use for rendering
*/ */
int GetFrameToUseForRendering() const; int GetFrameToUseForRendering() const;
/** /**
* @brief Sets the new Animation with all relevant information for rendering * @brief Sets the new Animation with all relevant information for rendering
* @param pData Pointer to Animation Data * @param pData Pointer to Animation Data
* @param numberOfFrames Number of Frames in Animation * @param numberOfFrames Number of Frames in Animation
* @param delayLen Delay after each Animation sequence * @param delayLen Delay after each Animation sequence
* @param flags Specifies what special logics are applied to this Animation * @param flags Specifies what special logics are applied to this Animation
* @param numSkippedFrames Number of Frames that will be skipped (for example with modifier "faster attack") * @param numSkippedFrames Number of Frames that will be skipped (for example with modifier "faster attack")
* @param distributeFramesBeforeFrame Distribute the numSkippedFrames only before this frame * @param distributeFramesBeforeFrame Distribute the numSkippedFrames only before this frame
*/ */
void SetNewAnimation(byte *pData, int numberOfFrames, int delayLen, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0); void SetNewAnimation(byte *pData, int numberOfFrames, int delayLen, AnimationDistributionFlags flags = AnimationDistributionFlags::None, int numSkippedFrames = 0, int distributeFramesBeforeFrame = 0);
/* /*
* @brief Process the Animation for a game tick (for example advances the frame) * @brief Process the Animation for a game tick (for example advances the frame)
*/ */
void ProcessAnimation(); void ProcessAnimation();
private: private:
/** /**
* @brief Specifies how many animations-fractions are displayed between two game ticks. this can be > 0, if animations are skipped or < 0 if the same animation is shown in multiple times (delay specified). * @brief Specifies how many animations-fractions are displayed between two game ticks. this can be > 0, if animations are skipped or < 0 if the same animation is shown in multiple times (delay specified).
*/ */
float TickModifier; float TickModifier;
/** /**
* @brief Number of game ticks after the current animation sequence started * @brief Number of game ticks after the current animation sequence started
*/ */
int TicksSinceSequenceStarted; int TicksSinceSequenceStarted;
/** /**
* @brief Animation Frames that will be adjusted for the skipped Frames/game ticks * @brief Animation Frames that will be adjusted for the skipped Frames/game ticks
*/ */
int RelevantFramesForDistributing; int RelevantFramesForDistributing;
/** /**
* @brief Animation Frames that wasn't shown from previous Animation * @brief Animation Frames that wasn't shown from previous Animation
*/ */
int SkippedFramesFromPreviousAnimation; int SkippedFramesFromPreviousAnimation;
}; };
} // namespace devilution } // namespace devilution

10
Source/storm/storm_dvlnet.h

@ -1,5 +1,5 @@
#pragma once #pragma once
void DvlNet_SendInfoRequest(); void DvlNet_SendInfoRequest();
std::vector<std::string> DvlNet_GetGamelist(); std::vector<std::string> DvlNet_GetGamelist();
void DvlNet_SetPassword(std::string pw); void DvlNet_SetPassword(std::string pw);

146
Source/utils/math.h

@ -1,73 +1,73 @@
/** /**
* @file math.h * @file math.h
* *
* Math utility functions * Math utility functions
*/ */
#pragma once #pragma once
namespace devilution { namespace devilution {
namespace math { namespace math {
/** /**
* @brief Compute sign of t * @brief Compute sign of t
* @tparam T Any arithmetic type * @tparam T Any arithmetic type
* @param t Value to compute sign of * @param t Value to compute sign of
* @return -1 if t < 0, 1 if t > 0, 0 if t == 0 * @return -1 if t < 0, 1 if t > 0, 0 if t == 0
*/ */
template <typename T> template <typename T>
int Sign(T t) int Sign(T t)
{ {
return (t > T(0)) - (t < T(0)); return (t > T(0)) - (t < T(0));
} }
/** /**
* @brief Linearly interpolate from a towards b using mixing value t * @brief Linearly interpolate from a towards b using mixing value t
* @tparam V Any arithmetic type, used for interpolants and return value * @tparam V Any arithmetic type, used for interpolants and return value
* @tparam T Any arithmetic type, used for interpolator * @tparam T Any arithmetic type, used for interpolator
* @param a Low interpolation value (returned when t == 0) * @param a Low interpolation value (returned when t == 0)
* @param b High interpolation value (returned when t == 1) * @param b High interpolation value (returned when t == 1)
* @param t Interpolator, commonly in range [0..1], values outside this range will extrapolate * @param t Interpolator, commonly in range [0..1], values outside this range will extrapolate
* @return a + (b - a) * t * @return a + (b - a) * t
*/ */
template <typename V, typename T> template <typename V, typename T>
V Lerp(V a, V b, T t) V Lerp(V a, V b, T t)
{ {
return a + (b - a) * t; return a + (b - a) * t;
} }
/** /**
* @brief Inverse lerp, given two key values a and b, and a free value v, determine mixing factor t so that v = Lerp(a, b, t) * @brief Inverse lerp, given two key values a and b, and a free value v, determine mixing factor t so that v = Lerp(a, b, t)
* @tparam T Any arithmetic type * @tparam T Any arithmetic type
* @param a Low key value (function returns 0 if v == a) * @param a Low key value (function returns 0 if v == a)
* @param b High key value (function returns 1 if v == b) * @param b High key value (function returns 1 if v == b)
* @param v Mixing factor, commonly in range [a..b] to get a return [0..1] * @param v Mixing factor, commonly in range [a..b] to get a return [0..1]
* @return Value t so that v = Lerp(a, b, t); or 0 if b == a * @return Value t so that v = Lerp(a, b, t); or 0 if b == a
*/ */
template <typename T> template <typename T>
T InvLerp(T a, T b, T v) T InvLerp(T a, T b, T v)
{ {
if (b == a) if (b == a)
return T(0); return T(0);
return (v - a) / (b - a); return (v - a) / (b - a);
} }
/** /**
* @brief Remaps value v from range [inMin, inMax] to [outMin, outMax] * @brief Remaps value v from range [inMin, inMax] to [outMin, outMax]
* @tparam T Any arithmetic type * @tparam T Any arithmetic type
* @param inMin First bound of input range * @param inMin First bound of input range
* @param inMax Second bound of input range * @param inMax Second bound of input range
* @param outMin First bound of output range * @param outMin First bound of output range
* @param outMax Second bound of output range * @param outMax Second bound of output range
* @param v Value to remap * @param v Value to remap
* @return Transformed value so that InvLerp(inMin, inMax, v) == InvLerp(outMin, outMax, return) * @return Transformed value so that InvLerp(inMin, inMax, v) == InvLerp(outMin, outMax, return)
*/ */
template <typename T> template <typename T>
T Remap(T inMin, T inMax, T outMin, T outMax, T v) T Remap(T inMin, T inMax, T outMin, T outMax, T v)
{ {
auto t = InvLerp(inMin, inMax, v); auto t = InvLerp(inMin, inMax, v);
return Lerp(outMin, outMax, t); return Lerp(outMin, outMax, t);
} }
} // namespace math } // namespace math
} // namespace devilution } // namespace devilution

38
Source/utils/stdcompat/string_view.hpp

@ -1,19 +1,19 @@
#pragma once #pragma once
#ifdef __has_include #ifdef __has_include
#if defined(__cplusplus) && __cplusplus >= 201703L && __has_include(<string_view>) // should be 201606L, but STL headers disagree #if defined(__cplusplus) && __cplusplus >= 201703L && __has_include(<string_view>) // should be 201606L, but STL headers disagree
#include <string_view> // IWYU pragma: export #include <string_view> // IWYU pragma: export
namespace devilution { namespace devilution {
using string_view = std::string_view; using string_view = std::string_view;
} }
#elif __has_include(<experimental/string_view>) #elif __has_include(<experimental/string_view>)
#include <experimental/string_view> // IWYU pragma: export #include <experimental/string_view> // IWYU pragma: export
namespace devilution { namespace devilution {
using string_view = std::experimental::string_view; using string_view = std::experimental::string_view;
} }
#else #else
#error "Missing support for <string_view> or <experimental/string_view>" #error "Missing support for <string_view> or <experimental/string_view>"
#endif #endif
#else #else
#error "__has_include unavailable" #error "__has_include unavailable"
#endif #endif

1048
test/animationinfo_test.cpp

File diff suppressed because it is too large Load Diff

62
test/appfat_test.cpp

@ -1,31 +1,31 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "appfat.h" #include "appfat.h"
#include "diablo.h" #include "diablo.h"
using namespace devilution; using namespace devilution;
TEST(Appfat, app_fatal) TEST(Appfat, app_fatal)
{ {
EXPECT_EXIT(app_fatal("test"), ::testing::ExitedWithCode(1), "test"); EXPECT_EXIT(app_fatal("test"), ::testing::ExitedWithCode(1), "test");
} }
TEST(Appfat, ErrDlg) TEST(Appfat, ErrDlg)
{ {
EXPECT_EXIT(ErrDlg("Title", "Unknown error", "appfat.cpp", 7), ::testing::ExitedWithCode(1), "Unknown error\n\nThe error occurred at: appfat.cpp line 7"); EXPECT_EXIT(ErrDlg("Title", "Unknown error", "appfat.cpp", 7), ::testing::ExitedWithCode(1), "Unknown error\n\nThe error occurred at: appfat.cpp line 7");
} }
TEST(Appfat, FileErrDlg) TEST(Appfat, FileErrDlg)
{ {
EXPECT_EXIT(FileErrDlg("devilution/image.cl2"), ::testing::ExitedWithCode(1), "devilution/image.cl2"); EXPECT_EXIT(FileErrDlg("devilution/image.cl2"), ::testing::ExitedWithCode(1), "devilution/image.cl2");
} }
TEST(Appfat, InsertCDDlg) TEST(Appfat, InsertCDDlg)
{ {
EXPECT_EXIT(InsertCDDlg(), ::testing::ExitedWithCode(1), "diabdat.mpq"); EXPECT_EXIT(InsertCDDlg(), ::testing::ExitedWithCode(1), "diabdat.mpq");
} }
TEST(Appfat, DirErrorDlg) TEST(Appfat, DirErrorDlg)
{ {
EXPECT_EXIT(DirErrorDlg("/"), ::testing::ExitedWithCode(1), "Unable to write to location:\n/"); EXPECT_EXIT(DirErrorDlg("/"), ::testing::ExitedWithCode(1), "Unable to write to location:\n/");
} }

254
test/automap_test.cpp

@ -1,127 +1,127 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "automap.h" #include "automap.h"
using namespace devilution; using namespace devilution;
TEST(Automap, InitAutomap) TEST(Automap, InitAutomap)
{ {
InitAutomapOnce(); InitAutomapOnce();
EXPECT_EQ(AutomapActive, false); EXPECT_EQ(AutomapActive, false);
EXPECT_EQ(AutoMapScale, 50); EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32); EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16); EXPECT_EQ(AmLine32, 16);
EXPECT_EQ(AmLine16, 8); EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4); EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2); EXPECT_EQ(AmLine4, 2);
} }
TEST(Automap, StartAutomap) TEST(Automap, StartAutomap)
{ {
StartAutomap(); StartAutomap();
EXPECT_EQ(AutomapOffset.x, 0); EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0); EXPECT_EQ(AutomapOffset.y, 0);
EXPECT_EQ(AutomapActive, true); EXPECT_EQ(AutomapActive, true);
} }
TEST(Automap, AutomapUp) TEST(Automap, AutomapUp)
{ {
AutomapOffset.x = 1; AutomapOffset.x = 1;
AutomapOffset.y = 1; AutomapOffset.y = 1;
AutomapUp(); AutomapUp();
EXPECT_EQ(AutomapOffset.x, 0); EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0); EXPECT_EQ(AutomapOffset.y, 0);
} }
TEST(Automap, AutomapDown) TEST(Automap, AutomapDown)
{ {
AutomapOffset.x = 1; AutomapOffset.x = 1;
AutomapOffset.y = 1; AutomapOffset.y = 1;
AutomapDown(); AutomapDown();
EXPECT_EQ(AutomapOffset.x, 2); EXPECT_EQ(AutomapOffset.x, 2);
EXPECT_EQ(AutomapOffset.y, 2); EXPECT_EQ(AutomapOffset.y, 2);
} }
TEST(Automap, AutomapLeft) TEST(Automap, AutomapLeft)
{ {
AutomapOffset.x = 1; AutomapOffset.x = 1;
AutomapOffset.y = 1; AutomapOffset.y = 1;
AutomapLeft(); AutomapLeft();
EXPECT_EQ(AutomapOffset.x, 0); EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 2); EXPECT_EQ(AutomapOffset.y, 2);
} }
TEST(Automap, AutomapRight) TEST(Automap, AutomapRight)
{ {
AutomapOffset.x = 1; AutomapOffset.x = 1;
AutomapOffset.y = 1; AutomapOffset.y = 1;
AutomapRight(); AutomapRight();
EXPECT_EQ(AutomapOffset.x, 2); EXPECT_EQ(AutomapOffset.x, 2);
EXPECT_EQ(AutomapOffset.y, 0); EXPECT_EQ(AutomapOffset.y, 0);
} }
TEST(Automap, AutomapZoomIn) TEST(Automap, AutomapZoomIn)
{ {
AutoMapScale = 50; AutoMapScale = 50;
AutomapZoomIn(); AutomapZoomIn();
EXPECT_EQ(AutoMapScale, 55); EXPECT_EQ(AutoMapScale, 55);
EXPECT_EQ(AmLine64, 35); EXPECT_EQ(AmLine64, 35);
EXPECT_EQ(AmLine32, 17); EXPECT_EQ(AmLine32, 17);
EXPECT_EQ(AmLine16, 8); EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4); EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2); EXPECT_EQ(AmLine4, 2);
} }
TEST(Automap, AutomapZoomIn_Max) TEST(Automap, AutomapZoomIn_Max)
{ {
AutoMapScale = 195; AutoMapScale = 195;
AutomapZoomIn(); AutomapZoomIn();
AutomapZoomIn(); AutomapZoomIn();
EXPECT_EQ(AutoMapScale, 200); EXPECT_EQ(AutoMapScale, 200);
EXPECT_EQ(AmLine64, 128); EXPECT_EQ(AmLine64, 128);
EXPECT_EQ(AmLine32, 64); EXPECT_EQ(AmLine32, 64);
EXPECT_EQ(AmLine16, 32); EXPECT_EQ(AmLine16, 32);
EXPECT_EQ(AmLine8, 16); EXPECT_EQ(AmLine8, 16);
EXPECT_EQ(AmLine4, 8); EXPECT_EQ(AmLine4, 8);
} }
TEST(Automap, AutomapZoomOut) TEST(Automap, AutomapZoomOut)
{ {
AutoMapScale = 200; AutoMapScale = 200;
AutomapZoomOut(); AutomapZoomOut();
EXPECT_EQ(AutoMapScale, 195); EXPECT_EQ(AutoMapScale, 195);
EXPECT_EQ(AmLine64, 124); EXPECT_EQ(AmLine64, 124);
EXPECT_EQ(AmLine32, 62); EXPECT_EQ(AmLine32, 62);
EXPECT_EQ(AmLine16, 31); EXPECT_EQ(AmLine16, 31);
EXPECT_EQ(AmLine8, 15); EXPECT_EQ(AmLine8, 15);
EXPECT_EQ(AmLine4, 7); EXPECT_EQ(AmLine4, 7);
} }
TEST(Automap, AutomapZoomOut_Min) TEST(Automap, AutomapZoomOut_Min)
{ {
AutoMapScale = 55; AutoMapScale = 55;
AutomapZoomOut(); AutomapZoomOut();
AutomapZoomOut(); AutomapZoomOut();
EXPECT_EQ(AutoMapScale, 50); EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32); EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16); EXPECT_EQ(AmLine32, 16);
EXPECT_EQ(AmLine16, 8); EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4); EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2); EXPECT_EQ(AmLine4, 2);
} }
TEST(Automap, AutomapZoomReset) TEST(Automap, AutomapZoomReset)
{ {
AutoMapScale = 50; AutoMapScale = 50;
AutomapOffset.x = 1; AutomapOffset.x = 1;
AutomapOffset.y = 1; AutomapOffset.y = 1;
AutomapZoomReset(); AutomapZoomReset();
EXPECT_EQ(AutomapOffset.x, 0); EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0); EXPECT_EQ(AutomapOffset.y, 0);
EXPECT_EQ(AutoMapScale, 50); EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32); EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16); EXPECT_EQ(AmLine32, 16);
EXPECT_EQ(AmLine16, 8); EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4); EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2); EXPECT_EQ(AmLine4, 2);
} }

30
test/codec_test.cpp

@ -1,15 +1,15 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "codec.h" #include "codec.h"
using namespace devilution; using namespace devilution;
TEST(Codec, codec_get_encoded_len) TEST(Codec, codec_get_encoded_len)
{ {
EXPECT_EQ(codec_get_encoded_len(50), 72); EXPECT_EQ(codec_get_encoded_len(50), 72);
} }
TEST(Codec, codec_get_encoded_len_eq) TEST(Codec, codec_get_encoded_len_eq)
{ {
EXPECT_EQ(codec_get_encoded_len(128), 136); EXPECT_EQ(codec_get_encoded_len(128), 136);
} }

58
test/control_test.cpp

@ -1,29 +1,29 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "control.h" #include "control.h"
using namespace devilution; using namespace devilution;
TEST(Control, SetSpell) TEST(Control, SetSpell)
{ {
pnumlines = 1; pnumlines = 1;
pinfoflag = true; pinfoflag = true;
pSpell = SPL_FIREBOLT; pSpell = SPL_FIREBOLT;
pSplType = RSPLTYPE_CHARGES; pSplType = RSPLTYPE_CHARGES;
SetSpell(); SetSpell();
EXPECT_EQ(spselflag, false); EXPECT_EQ(spselflag, false);
EXPECT_EQ(plr[myplr]._pRSpell, SPL_FIREBOLT); EXPECT_EQ(plr[myplr]._pRSpell, SPL_FIREBOLT);
EXPECT_EQ(plr[myplr]._pRSplType, RSPLTYPE_CHARGES); EXPECT_EQ(plr[myplr]._pRSplType, RSPLTYPE_CHARGES);
EXPECT_EQ(pnumlines, 0); EXPECT_EQ(pnumlines, 0);
EXPECT_EQ(pinfoflag, false); EXPECT_EQ(pinfoflag, false);
EXPECT_EQ(force_redraw, 255); EXPECT_EQ(force_redraw, 255);
} }
TEST(Control, ClearPanel) TEST(Control, ClearPanel)
{ {
pnumlines = 1; pnumlines = 1;
pinfoflag = true; pinfoflag = true;
ClearPanel(); ClearPanel();
EXPECT_EQ(pnumlines, 0); EXPECT_EQ(pnumlines, 0);
EXPECT_EQ(pinfoflag, false); EXPECT_EQ(pinfoflag, false);
} }

38
test/cursor_test.cpp

@ -1,19 +1,19 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "cursor.h" #include "cursor.h"
#include "itemdat.h" #include "itemdat.h"
using namespace devilution; using namespace devilution;
TEST(Cursor, SetCursor) TEST(Cursor, SetCursor)
{ {
int i = ICURS_SPIKED_CLUB + CURSOR_FIRSTITEM; int i = ICURS_SPIKED_CLUB + CURSOR_FIRSTITEM;
NewCursor(i); NewCursor(i);
EXPECT_EQ(pcurs, i); EXPECT_EQ(pcurs, i);
EXPECT_EQ(cursW, 1 * 28); EXPECT_EQ(cursW, 1 * 28);
EXPECT_EQ(cursH, 3 * 28); EXPECT_EQ(cursH, 3 * 28);
EXPECT_EQ(icursW, 1 * 28); EXPECT_EQ(icursW, 1 * 28);
EXPECT_EQ(icursH, 3 * 28); EXPECT_EQ(icursH, 3 * 28);
EXPECT_EQ(icursW28, 1); EXPECT_EQ(icursW28, 1);
EXPECT_EQ(icursH28, 3); EXPECT_EQ(icursH28, 3);
} }

38
test/dead_test.cpp

@ -1,19 +1,19 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "dead.h" #include "dead.h"
#include "engine.h" #include "engine.h"
#include "gendung.h" #include "gendung.h"
using namespace devilution; using namespace devilution;
TEST(Dead, AddDead) TEST(Dead, AddDead)
{ {
AddDead({21, 48}, 8, DIR_W); AddDead({21, 48}, 8, DIR_W);
EXPECT_EQ(dDead[21][48], 8 + (DIR_W << 5)); EXPECT_EQ(dDead[21][48], 8 + (DIR_W << 5));
} }
TEST(Dead, AddDead_OOB) TEST(Dead, AddDead_OOB)
{ {
AddDead({21, 48}, MaxDead + 1, DIR_W); AddDead({21, 48}, MaxDead + 1, DIR_W);
EXPECT_EQ(dDead[21][48], 0 + (DIR_W << 5)); EXPECT_EQ(dDead[21][48], 0 + (DIR_W << 5));
} }

28
test/diablo_test.cpp

@ -1,14 +1,14 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "diablo.h" #include "diablo.h"
#include "multi.h" #include "multi.h"
using namespace devilution; using namespace devilution;
TEST(Diablo, diablo_pause_game_unpause) TEST(Diablo, diablo_pause_game_unpause)
{ {
gbIsMultiplayer = false; gbIsMultiplayer = false;
PauseMode = 1; PauseMode = 1;
diablo_pause_game(); diablo_pause_game();
EXPECT_EQ(PauseMode, 0); EXPECT_EQ(PauseMode, 0);
} }

34
test/doom_test.cpp

@ -1,17 +1,17 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "doom.h" #include "doom.h"
using namespace devilution; using namespace devilution;
TEST(Doom, doom_get_frame_from_time) TEST(Doom, doom_get_frame_from_time)
{ {
DoomQuestState = 1200 * 8 + 548; DoomQuestState = 1200 * 8 + 548;
EXPECT_EQ(doom_get_frame_from_time(), 8); EXPECT_EQ(doom_get_frame_from_time(), 8);
} }
TEST(Doom, doom_get_frame_from_time_max) TEST(Doom, doom_get_frame_from_time_max)
{ {
DoomQuestState = 1200 * 30 + 1; DoomQuestState = 1200 * 30 + 1;
EXPECT_EQ(doom_get_frame_from_time(), 31); EXPECT_EQ(doom_get_frame_from_time(), 31);
} }

42
test/drlg_l1_test.cpp

@ -1,21 +1,21 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "diablo.h" #include "diablo.h"
#include "drlg_l1.h" #include "drlg_l1.h"
#include "lighting.h" #include "lighting.h"
using namespace devilution; using namespace devilution;
TEST(Drlg_l1, DRLG_Init_Globals_noflag) TEST(Drlg_l1, DRLG_Init_Globals_noflag)
{ {
lightflag = false; lightflag = false;
DRLG_Init_Globals(); DRLG_Init_Globals();
EXPECT_EQ(dLight[0][0], 15); EXPECT_EQ(dLight[0][0], 15);
} }
TEST(Drlg_l1, DRLG_Init_Globals) TEST(Drlg_l1, DRLG_Init_Globals)
{ {
lightflag = true; lightflag = true;
DRLG_Init_Globals(); DRLG_Init_Globals();
EXPECT_EQ(dLight[0][0], 0); EXPECT_EQ(dLight[0][0], 0);
} }

24
test/drlg_l2_test.cpp

@ -1,12 +1,12 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "drlg_l2.h" #include "drlg_l2.h"
using namespace devilution; using namespace devilution;
TEST(Drlg_l2, InitDungeon) TEST(Drlg_l2, InitDungeon)
{ {
InitDungeon(); InitDungeon();
EXPECT_EQ(predungeon[0][0], 32); EXPECT_EQ(predungeon[0][0], 32);
EXPECT_EQ(dflags[0][0], 0); EXPECT_EQ(dflags[0][0], 0);
} }

70
test/drlg_l3_test.cpp

@ -1,35 +1,35 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "drlg_l3.h" #include "drlg_l3.h"
using namespace devilution; using namespace devilution;
TEST(Drlg_l3, AddFenceDoors_x) TEST(Drlg_l3, AddFenceDoors_x)
{ {
memset(dungeon, 0, sizeof(dungeon)); memset(dungeon, 0, sizeof(dungeon));
dungeon[5][5] = 7; dungeon[5][5] = 7;
dungeon[5 - 1][5] = 130; dungeon[5 - 1][5] = 130;
dungeon[5 + 1][5] = 152; dungeon[5 + 1][5] = 152;
AddFenceDoors(); AddFenceDoors();
EXPECT_EQ(dungeon[5][5], 146); EXPECT_EQ(dungeon[5][5], 146);
} }
TEST(Drlg_l3, AddFenceDoors_y) TEST(Drlg_l3, AddFenceDoors_y)
{ {
memset(dungeon, 0, sizeof(dungeon)); memset(dungeon, 0, sizeof(dungeon));
dungeon[5][5] = 7; dungeon[5][5] = 7;
dungeon[5][5 - 1] = 130; dungeon[5][5 - 1] = 130;
dungeon[5][5 + 1] = 152; dungeon[5][5 + 1] = 152;
AddFenceDoors(); AddFenceDoors();
EXPECT_EQ(dungeon[5][5], 147); EXPECT_EQ(dungeon[5][5], 147);
} }
TEST(Drlg_l3, AddFenceDoors_no) TEST(Drlg_l3, AddFenceDoors_no)
{ {
memset(dungeon, 0, sizeof(dungeon)); memset(dungeon, 0, sizeof(dungeon));
dungeon[5][5] = 7; dungeon[5][5] = 7;
dungeon[5 - 1][5] = 130; dungeon[5 - 1][5] = 130;
dungeon[5 + 1][5] = 153; dungeon[5 + 1][5] = 153;
AddFenceDoors(); AddFenceDoors();
EXPECT_EQ(dungeon[5][5], 7); EXPECT_EQ(dungeon[5][5], 7);
} }

42
test/drlg_l4_test.cpp

@ -1,21 +1,21 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "drlg_l4.h" #include "drlg_l4.h"
using namespace devilution; using namespace devilution;
TEST(Drlg_l4, IsDURWall) TEST(Drlg_l4, IsDURWall)
{ {
EXPECT_EQ(IsDURWall(25), true); EXPECT_EQ(IsDURWall(25), true);
EXPECT_EQ(IsDURWall(28), true); EXPECT_EQ(IsDURWall(28), true);
EXPECT_EQ(IsDURWall(23), true); EXPECT_EQ(IsDURWall(23), true);
EXPECT_EQ(IsDURWall(20), false); EXPECT_EQ(IsDURWall(20), false);
} }
TEST(Drlg_l4, IsDLLWall) TEST(Drlg_l4, IsDLLWall)
{ {
EXPECT_EQ(IsDLLWall(27), true); EXPECT_EQ(IsDLLWall(27), true);
EXPECT_EQ(IsDLLWall(26), true); EXPECT_EQ(IsDLLWall(26), true);
EXPECT_EQ(IsDLLWall(22), true); EXPECT_EQ(IsDLLWall(22), true);
EXPECT_EQ(IsDLLWall(20), false); EXPECT_EQ(IsDLLWall(20), false);
} }

112
test/effects_test.cpp

@ -1,56 +1,56 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "effects.h" #include "effects.h"
#include "player.h" #include "player.h"
using namespace devilution; using namespace devilution;
TEST(Effects, calc_snd_position_center) TEST(Effects, calc_snd_position_center)
{ {
plr[myplr].position.tile = { 50, 50 }; plr[myplr].position.tile = { 50, 50 };
int plVolume = 0; int plVolume = 0;
int plPan = 0; int plPan = 0;
EXPECT_EQ(calc_snd_position(50, 50, &plVolume, &plPan), true); EXPECT_EQ(calc_snd_position(50, 50, &plVolume, &plPan), true);
EXPECT_EQ(plVolume, 0); EXPECT_EQ(plVolume, 0);
EXPECT_EQ(plPan, 0); EXPECT_EQ(plPan, 0);
} }
TEST(Effects, calc_snd_position_near) TEST(Effects, calc_snd_position_near)
{ {
plr[myplr].position.tile = { 50, 50 }; plr[myplr].position.tile = { 50, 50 };
int plVolume = 0; int plVolume = 0;
int plPan = 0; int plPan = 0;
EXPECT_EQ(calc_snd_position(55, 50, &plVolume, &plPan), true); EXPECT_EQ(calc_snd_position(55, 50, &plVolume, &plPan), true);
EXPECT_EQ(plVolume, -320); EXPECT_EQ(plVolume, -320);
EXPECT_EQ(plPan, 1280); EXPECT_EQ(plPan, 1280);
} }
TEST(Effects, calc_snd_position_out_of_range) TEST(Effects, calc_snd_position_out_of_range)
{ {
plr[myplr].position.tile = { 12, 12 }; plr[myplr].position.tile = { 12, 12 };
int plVolume = 1234; int plVolume = 1234;
int plPan = 0; int plPan = 0;
EXPECT_EQ(calc_snd_position(112, 112, &plVolume, &plPan), false); EXPECT_EQ(calc_snd_position(112, 112, &plVolume, &plPan), false);
EXPECT_EQ(plVolume, 1234); EXPECT_EQ(plVolume, 1234);
EXPECT_EQ(plPan, 0); EXPECT_EQ(plPan, 0);
} }
TEST(Effects, calc_snd_position_extreme_right) TEST(Effects, calc_snd_position_extreme_right)
{ {
plr[myplr].position.tile = { 50, 50 }; plr[myplr].position.tile = { 50, 50 };
int plVolume = 0; int plVolume = 0;
int plPan = 0; int plPan = 0;
EXPECT_EQ(calc_snd_position(75, 25, &plVolume, &plPan), true); EXPECT_EQ(calc_snd_position(75, 25, &plVolume, &plPan), true);
EXPECT_EQ(plVolume, -2176); EXPECT_EQ(plVolume, -2176);
EXPECT_EQ(plPan, 6400); EXPECT_EQ(plPan, 6400);
} }
TEST(Effects, calc_snd_position_extreme_left) TEST(Effects, calc_snd_position_extreme_left)
{ {
plr[myplr].position.tile = { 50, 50 }; plr[myplr].position.tile = { 50, 50 };
int plVolume = 0; int plVolume = 0;
int plPan = 0; int plPan = 0;
EXPECT_EQ(calc_snd_position(25, 75, &plVolume, &plPan), true); EXPECT_EQ(calc_snd_position(25, 75, &plVolume, &plPan), true);
EXPECT_EQ(plVolume, -2176); EXPECT_EQ(plVolume, -2176);
EXPECT_EQ(plPan, -6400); EXPECT_EQ(plPan, -6400);
} }

452
test/inv_test.cpp

@ -1,226 +1,226 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "cursor.h" #include "cursor.h"
#include "inv.h" #include "inv.h"
#include "player.h" #include "player.h"
using namespace devilution; using namespace devilution;
/* Set up a given item as a spell scroll, allowing for its usage. */ /* Set up a given item as a spell scroll, allowing for its usage. */
void set_up_scroll(ItemStruct &item, spell_id spell) void set_up_scroll(ItemStruct &item, spell_id spell)
{ {
pcurs = CURSOR_HAND; pcurs = CURSOR_HAND;
leveltype = DTYPE_CATACOMBS; leveltype = DTYPE_CATACOMBS;
plr[myplr]._pRSpell = static_cast<spell_id>(spell); plr[myplr]._pRSpell = static_cast<spell_id>(spell);
item._itype = ITYPE_MISC; item._itype = ITYPE_MISC;
item._iMiscId = IMISC_SCROLL; item._iMiscId = IMISC_SCROLL;
item._iSpell = spell; item._iSpell = spell;
} }
/* Clear the inventory of myplr. */ /* Clear the inventory of myplr. */
void clear_inventory() void clear_inventory()
{ {
for (int i = 0; i < NUM_INV_GRID_ELEM; i++) { for (int i = 0; i < NUM_INV_GRID_ELEM; i++) {
memset(&plr[myplr].InvList[i], 0, sizeof(ItemStruct)); memset(&plr[myplr].InvList[i], 0, sizeof(ItemStruct));
plr[myplr].InvGrid[i] = 0; plr[myplr].InvGrid[i] = 0;
} }
plr[myplr]._pNumInv = 0; plr[myplr]._pNumInv = 0;
} }
// Test that the scroll is used in the inventory in correct conditions // Test that the scroll is used in the inventory in correct conditions
TEST(Inv, UseScroll_from_inventory) TEST(Inv, UseScroll_from_inventory)
{ {
set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT);
plr[myplr]._pNumInv = 5; plr[myplr]._pNumInv = 5;
EXPECT_TRUE(UseScroll()); EXPECT_TRUE(UseScroll());
} }
// Test that the scroll is used in the belt in correct conditions // Test that the scroll is used in the belt in correct conditions
TEST(Inv, UseScroll_from_belt) TEST(Inv, UseScroll_from_belt)
{ {
set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT);
EXPECT_TRUE(UseScroll()); EXPECT_TRUE(UseScroll());
} }
// Test that the scroll is not used in the inventory for each invalid condition // Test that the scroll is not used in the inventory for each invalid condition
TEST(Inv, UseScroll_from_inventory_invalid_conditions) TEST(Inv, UseScroll_from_inventory_invalid_conditions)
{ {
// Empty the belt to prevent using a scroll from the belt // Empty the belt to prevent using a scroll from the belt
for (int i = 0; i < MAXBELTITEMS; i++) { for (int i = 0; i < MAXBELTITEMS; i++) {
plr[myplr].SpdList[i]._itype = ITYPE_NONE; plr[myplr].SpdList[i]._itype = ITYPE_NONE;
} }
set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT);
pcurs = CURSOR_IDENTIFY; pcurs = CURSOR_IDENTIFY;
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT);
leveltype = DTYPE_TOWN; leveltype = DTYPE_TOWN;
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT);
plr[myplr]._pRSpell = static_cast<spell_id>(SPL_HEAL); plr[myplr]._pRSpell = static_cast<spell_id>(SPL_HEAL);
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT);
plr[myplr].InvList[2]._iMiscId = IMISC_STAFF; plr[myplr].InvList[2]._iMiscId = IMISC_STAFF;
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].InvList[2], SPL_FIREBOLT);
plr[myplr].InvList[2]._itype = ITYPE_NONE; plr[myplr].InvList[2]._itype = ITYPE_NONE;
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
} }
// Test that the scroll is not used in the belt for each invalid condition // Test that the scroll is not used in the belt for each invalid condition
TEST(Inv, UseScroll_from_belt_invalid_conditions) TEST(Inv, UseScroll_from_belt_invalid_conditions)
{ {
// Disable the inventory to prevent using a scroll from the inventory // Disable the inventory to prevent using a scroll from the inventory
plr[myplr]._pNumInv = 0; plr[myplr]._pNumInv = 0;
set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT);
pcurs = CURSOR_IDENTIFY; pcurs = CURSOR_IDENTIFY;
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT);
leveltype = DTYPE_TOWN; leveltype = DTYPE_TOWN;
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT);
plr[myplr]._pRSpell = static_cast<spell_id>(SPL_HEAL); plr[myplr]._pRSpell = static_cast<spell_id>(SPL_HEAL);
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT);
plr[myplr].SpdList[2]._iMiscId = IMISC_STAFF; plr[myplr].SpdList[2]._iMiscId = IMISC_STAFF;
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT); set_up_scroll(plr[myplr].SpdList[2], SPL_FIREBOLT);
plr[myplr].SpdList[2]._itype = ITYPE_NONE; plr[myplr].SpdList[2]._itype = ITYPE_NONE;
EXPECT_FALSE(UseScroll()); EXPECT_FALSE(UseScroll());
} }
// Test gold calculation // Test gold calculation
TEST(Inv, CalculateGold) TEST(Inv, CalculateGold)
{ {
plr[myplr]._pNumInv = 10; plr[myplr]._pNumInv = 10;
// Set up two slots of gold both in the belt and inventory // Set up two slots of gold both in the belt and inventory
plr[myplr].SpdList[1]._itype = ITYPE_GOLD; plr[myplr].SpdList[1]._itype = ITYPE_GOLD;
plr[myplr].SpdList[5]._itype = ITYPE_GOLD; plr[myplr].SpdList[5]._itype = ITYPE_GOLD;
plr[myplr].InvList[2]._itype = ITYPE_GOLD; plr[myplr].InvList[2]._itype = ITYPE_GOLD;
plr[myplr].InvList[3]._itype = ITYPE_GOLD; plr[myplr].InvList[3]._itype = ITYPE_GOLD;
// Set the gold amount to arbitrary values // Set the gold amount to arbitrary values
plr[myplr].SpdList[1]._ivalue = 100; plr[myplr].SpdList[1]._ivalue = 100;
plr[myplr].SpdList[5]._ivalue = 200; plr[myplr].SpdList[5]._ivalue = 200;
plr[myplr].InvList[2]._ivalue = 3; plr[myplr].InvList[2]._ivalue = 3;
plr[myplr].InvList[3]._ivalue = 30; plr[myplr].InvList[3]._ivalue = 30;
EXPECT_EQ(CalculateGold(myplr), 333); EXPECT_EQ(CalculateGold(myplr), 333);
} }
// Test automatic gold placing // Test automatic gold placing
TEST(Inv, GoldAutoPlace) TEST(Inv, GoldAutoPlace)
{ {
// Empty the inventory // Empty the inventory
clear_inventory(); clear_inventory();
// Put gold into the inventory: // Put gold into the inventory:
// | 1000 | ... | ... // | 1000 | ... | ...
plr[myplr].InvList[0]._itype = ITYPE_GOLD; plr[myplr].InvList[0]._itype = ITYPE_GOLD;
plr[myplr].InvList[0]._ivalue = 1000; plr[myplr].InvList[0]._ivalue = 1000;
plr[myplr]._pNumInv = 1; plr[myplr]._pNumInv = 1;
// Put (max gold - 100) gold, which is 4900, into the player's hand // Put (max gold - 100) gold, which is 4900, into the player's hand
plr[myplr].HoldItem._itype = ITYPE_GOLD; plr[myplr].HoldItem._itype = ITYPE_GOLD;
plr[myplr].HoldItem._ivalue = GOLD_MAX_LIMIT - 100; plr[myplr].HoldItem._ivalue = GOLD_MAX_LIMIT - 100;
GoldAutoPlace(myplr); GoldAutoPlace(myplr);
// We expect the inventory: // We expect the inventory:
// | 5000 | 900 | ... // | 5000 | 900 | ...
EXPECT_EQ(plr[myplr].InvList[0]._ivalue, GOLD_MAX_LIMIT); EXPECT_EQ(plr[myplr].InvList[0]._ivalue, GOLD_MAX_LIMIT);
EXPECT_EQ(plr[myplr].InvList[1]._ivalue, 900); EXPECT_EQ(plr[myplr].InvList[1]._ivalue, 900);
} }
// Test removing an item from inventory with no other items. // Test removing an item from inventory with no other items.
TEST(Inv, RemoveInvItem) TEST(Inv, RemoveInvItem)
{ {
clear_inventory(); clear_inventory();
// Put a two-slot misc item into the inventory: // Put a two-slot misc item into the inventory:
// | (item) | (item) | ... | ... // | (item) | (item) | ... | ...
plr[myplr]._pNumInv = 1; plr[myplr]._pNumInv = 1;
plr[myplr].InvGrid[0] = 1; plr[myplr].InvGrid[0] = 1;
plr[myplr].InvGrid[1] = -1; plr[myplr].InvGrid[1] = -1;
plr[myplr].InvList[0]._itype = ITYPE_MISC; plr[myplr].InvList[0]._itype = ITYPE_MISC;
plr[myplr].RemoveInvItem(0); plr[myplr].RemoveInvItem(0);
EXPECT_EQ(plr[myplr].InvGrid[0], 0); EXPECT_EQ(plr[myplr].InvGrid[0], 0);
EXPECT_EQ(plr[myplr].InvGrid[1], 0); EXPECT_EQ(plr[myplr].InvGrid[1], 0);
EXPECT_EQ(plr[myplr]._pNumInv, 0); EXPECT_EQ(plr[myplr]._pNumInv, 0);
} }
// Test removing an item from inventory with other items in it. // Test removing an item from inventory with other items in it.
TEST(Inv, RemoveInvItem_other_item) TEST(Inv, RemoveInvItem_other_item)
{ {
clear_inventory(); clear_inventory();
// Put a two-slot misc item and a ring into the inventory: // Put a two-slot misc item and a ring into the inventory:
// | (item) | (item) | (ring) | ... // | (item) | (item) | (ring) | ...
plr[myplr]._pNumInv = 2; plr[myplr]._pNumInv = 2;
plr[myplr].InvGrid[0] = 1; plr[myplr].InvGrid[0] = 1;
plr[myplr].InvGrid[1] = -1; plr[myplr].InvGrid[1] = -1;
plr[myplr].InvList[0]._itype = ITYPE_MISC; plr[myplr].InvList[0]._itype = ITYPE_MISC;
plr[myplr].InvGrid[2] = 2; plr[myplr].InvGrid[2] = 2;
plr[myplr].InvList[1]._itype = ITYPE_RING; plr[myplr].InvList[1]._itype = ITYPE_RING;
plr[myplr].RemoveInvItem(0); plr[myplr].RemoveInvItem(0);
EXPECT_EQ(plr[myplr].InvGrid[0], 0); EXPECT_EQ(plr[myplr].InvGrid[0], 0);
EXPECT_EQ(plr[myplr].InvGrid[1], 0); EXPECT_EQ(plr[myplr].InvGrid[1], 0);
EXPECT_EQ(plr[myplr].InvGrid[2], 1); EXPECT_EQ(plr[myplr].InvGrid[2], 1);
EXPECT_EQ(plr[myplr].InvList[0]._itype, ITYPE_RING); EXPECT_EQ(plr[myplr].InvList[0]._itype, ITYPE_RING);
EXPECT_EQ(plr[myplr]._pNumInv, 1); EXPECT_EQ(plr[myplr]._pNumInv, 1);
} }
// Test removing an item from the belt // Test removing an item from the belt
TEST(Inv, RemoveSpdBarItem) TEST(Inv, RemoveSpdBarItem)
{ {
// Clear the belt // Clear the belt
for (int i = 0; i < MAXBELTITEMS; i++) { for (int i = 0; i < MAXBELTITEMS; i++) {
plr[myplr].SpdList[i]._itype = ITYPE_NONE; plr[myplr].SpdList[i]._itype = ITYPE_NONE;
} }
// Put an item in the belt: | x | x | item | x | x | x | x | x | // Put an item in the belt: | x | x | item | x | x | x | x | x |
plr[myplr].SpdList[3]._itype = ITYPE_MISC; plr[myplr].SpdList[3]._itype = ITYPE_MISC;
RemoveSpdBarItem(myplr, 3); RemoveSpdBarItem(myplr, 3);
EXPECT_EQ(plr[myplr].SpdList[3]._itype, ITYPE_NONE); EXPECT_EQ(plr[myplr].SpdList[3]._itype, ITYPE_NONE);
} }
// Test removing a scroll from the inventory // Test removing a scroll from the inventory
TEST(Inv, RemoveScroll_inventory) TEST(Inv, RemoveScroll_inventory)
{ {
clear_inventory(); clear_inventory();
// Put a firebolt scroll into the inventory // Put a firebolt scroll into the inventory
plr[myplr]._pNumInv = 1; plr[myplr]._pNumInv = 1;
plr[myplr]._pRSpell = static_cast<spell_id>(SPL_FIREBOLT); plr[myplr]._pRSpell = static_cast<spell_id>(SPL_FIREBOLT);
plr[myplr].InvList[0]._itype = ITYPE_MISC; plr[myplr].InvList[0]._itype = ITYPE_MISC;
plr[myplr].InvList[0]._iMiscId = IMISC_SCROLL; plr[myplr].InvList[0]._iMiscId = IMISC_SCROLL;
plr[myplr].InvList[0]._iSpell = SPL_FIREBOLT; plr[myplr].InvList[0]._iSpell = SPL_FIREBOLT;
RemoveScroll(myplr); RemoveScroll(myplr);
EXPECT_EQ(plr[myplr].InvGrid[0], 0); EXPECT_EQ(plr[myplr].InvGrid[0], 0);
EXPECT_EQ(plr[myplr]._pNumInv, 0); EXPECT_EQ(plr[myplr]._pNumInv, 0);
} }
// Test removing a scroll from the belt // Test removing a scroll from the belt
TEST(Inv, RemoveScroll_belt) TEST(Inv, RemoveScroll_belt)
{ {
// Clear the belt // Clear the belt
for (int i = 0; i < MAXBELTITEMS; i++) { for (int i = 0; i < MAXBELTITEMS; i++) {
plr[myplr].SpdList[i]._itype = ITYPE_NONE; plr[myplr].SpdList[i]._itype = ITYPE_NONE;
} }
// Put a firebolt scroll into the belt // Put a firebolt scroll into the belt
plr[myplr]._pSpell = static_cast<spell_id>(SPL_FIREBOLT); plr[myplr]._pSpell = static_cast<spell_id>(SPL_FIREBOLT);
plr[myplr].SpdList[3]._itype = ITYPE_MISC; plr[myplr].SpdList[3]._itype = ITYPE_MISC;
plr[myplr].SpdList[3]._iMiscId = IMISC_SCROLL; plr[myplr].SpdList[3]._iMiscId = IMISC_SCROLL;
plr[myplr].SpdList[3]._iSpell = SPL_FIREBOLT; plr[myplr].SpdList[3]._iSpell = SPL_FIREBOLT;
RemoveScroll(myplr); RemoveScroll(myplr);
EXPECT_EQ(plr[myplr].SpdList[3]._itype, ITYPE_NONE); EXPECT_EQ(plr[myplr].SpdList[3]._itype, ITYPE_NONE);
} }

76
test/lighting_test.cpp

@ -1,38 +1,38 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "control.h" #include "control.h"
#include "lighting.h" #include "lighting.h"
using namespace devilution; using namespace devilution;
TEST(Lighting, CrawlTables) TEST(Lighting, CrawlTables)
{ {
int CrawlNum[19] = { 0, 3, 12, 45, 94, 159, 240, 337, 450, 579, 724, 885, 1062, 1255, 1464, 1689, 1930, 2187, 2460 }; int CrawlNum[19] = { 0, 3, 12, 45, 94, 159, 240, 337, 450, 579, 724, 885, 1062, 1255, 1464, 1689, 1930, 2187, 2460 };
bool added[40][40]; bool added[40][40];
memset(added, 0, sizeof(added)); memset(added, 0, sizeof(added));
for (int j = 0; j < 19; j++) { for (int j = 0; j < 19; j++) {
int x = 20; int x = 20;
int y = 20; int y = 20;
int cr = CrawlNum[j] + 1; int cr = CrawlNum[j] + 1;
for (unsigned i = (uint8_t)CrawlTable[cr - 1]; i > 0; i--, cr += 2) { for (unsigned i = (uint8_t)CrawlTable[cr - 1]; i > 0; i--, cr += 2) {
int dx = x + CrawlTable[cr]; int dx = x + CrawlTable[cr];
int dy = y + CrawlTable[cr + 1]; int dy = y + CrawlTable[cr + 1];
sprintf(tempstr, "location %d:%d added twice.", dx - 20, dy - 20); sprintf(tempstr, "location %d:%d added twice.", dx - 20, dy - 20);
EXPECT_EQ(added[dx][dy], false) << tempstr; EXPECT_EQ(added[dx][dy], false) << tempstr;
added[dx][dy] = true; added[dx][dy] = true;
} }
} }
for (int i = -18; i <= 18; i++) { for (int i = -18; i <= 18; i++) {
for (int j = -18; j <= 18; j++) { for (int j = -18; j <= 18; j++) {
if (added[i + 20][j + 20]) if (added[i + 20][j + 20])
continue; continue;
if ((i == -18 && j == -18) || (i == -18 && j == 18) || (i == 18 && j == -18) || (i == 18 && j == 18)) if ((i == -18 && j == -18) || (i == -18 && j == 18) || (i == 18 && j == -18) || (i == 18 && j == 18))
continue; // Limit of the crawl table rage continue; // Limit of the crawl table rage
sprintf(tempstr, "while checking location %d:%d.", i, j); sprintf(tempstr, "while checking location %d:%d.", i, j);
EXPECT_EQ(false, true) << tempstr; EXPECT_EQ(false, true) << tempstr;
} }
} }
} }

174
test/missiles_test.cpp

@ -1,87 +1,87 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "missiles.h" #include "missiles.h"
using namespace devilution; using namespace devilution;
TEST(Missiles, GetDirection8) TEST(Missiles, GetDirection8)
{ {
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 15 })); EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 15 }));
EXPECT_EQ(1, GetDirection({ 0, 0 }, { 0, 15 })); EXPECT_EQ(1, GetDirection({ 0, 0 }, { 0, 15 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 15 })); EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 15 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 8 })); EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 8 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 8 })); EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 8 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 7 })); EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 7 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 11, 7 })); EXPECT_EQ(0, GetDirection({ 0, 0 }, { 11, 7 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 11 })); EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 11 }));
EXPECT_EQ(4, GetDirection({ 15, 15 }, { 0, 0 })); EXPECT_EQ(4, GetDirection({ 15, 15 }, { 0, 0 }));
EXPECT_EQ(5, GetDirection({ 0, 15 }, { 0, 0 })); EXPECT_EQ(5, GetDirection({ 0, 15 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 8, 15 }, { 0, 0 })); EXPECT_EQ(4, GetDirection({ 8, 15 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 8, 8 }, { 0, 0 })); EXPECT_EQ(4, GetDirection({ 8, 8 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 15, 8 }, { 0, 0 })); EXPECT_EQ(4, GetDirection({ 15, 8 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 15, 7 }, { 0, 0 })); EXPECT_EQ(4, GetDirection({ 15, 7 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 11, 7 }, { 0, 0 })); EXPECT_EQ(4, GetDirection({ 11, 7 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 8, 11 }, { 0, 0 })); EXPECT_EQ(4, GetDirection({ 8, 11 }, { 0, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 15 }, { 15, 0 })); EXPECT_EQ(6, GetDirection({ 0, 15 }, { 15, 0 }));
EXPECT_EQ(7, GetDirection({ 0, 0 }, { 15, 0 })); EXPECT_EQ(7, GetDirection({ 0, 0 }, { 15, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 8 }, { 15, 0 })); EXPECT_EQ(6, GetDirection({ 0, 8 }, { 15, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 8 }, { 8, 0 })); EXPECT_EQ(6, GetDirection({ 0, 8 }, { 8, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 15 }, { 8, 0 })); EXPECT_EQ(6, GetDirection({ 0, 15 }, { 8, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 15 }, { 7, 0 })); EXPECT_EQ(6, GetDirection({ 0, 15 }, { 7, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 11 }, { 7, 0 })); EXPECT_EQ(6, GetDirection({ 0, 11 }, { 7, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 8 }, { 11, 0 })); EXPECT_EQ(6, GetDirection({ 0, 8 }, { 11, 0 }));
EXPECT_EQ(0, GetDirection({ 1, 1 }, { 2, 2 })); EXPECT_EQ(0, GetDirection({ 1, 1 }, { 2, 2 }));
EXPECT_EQ(1, GetDirection({ 1, 1 }, { 1, 2 })); EXPECT_EQ(1, GetDirection({ 1, 1 }, { 1, 2 }));
EXPECT_EQ(2, GetDirection({ 1, 1 }, { 0, 2 })); EXPECT_EQ(2, GetDirection({ 1, 1 }, { 0, 2 }));
EXPECT_EQ(3, GetDirection({ 1, 1 }, { 0, 1 })); EXPECT_EQ(3, GetDirection({ 1, 1 }, { 0, 1 }));
EXPECT_EQ(4, GetDirection({ 1, 1 }, { 0, 0 })); EXPECT_EQ(4, GetDirection({ 1, 1 }, { 0, 0 }));
EXPECT_EQ(5, GetDirection({ 1, 1 }, { 1, 0 })); EXPECT_EQ(5, GetDirection({ 1, 1 }, { 1, 0 }));
EXPECT_EQ(6, GetDirection({ 1, 1 }, { 2, 0 })); EXPECT_EQ(6, GetDirection({ 1, 1 }, { 2, 0 }));
EXPECT_EQ(7, GetDirection({ 1, 1 }, { 2, 1 })); EXPECT_EQ(7, GetDirection({ 1, 1 }, { 2, 1 }));
} }
TEST(Missiles, GetDirection16) TEST(Missiles, GetDirection16)
{ {
EXPECT_EQ(0, GetDirection16(0, 0, 15, 15)); EXPECT_EQ(0, GetDirection16(0, 0, 15, 15));
EXPECT_EQ(2, GetDirection16(0, 0, 0, 15)); EXPECT_EQ(2, GetDirection16(0, 0, 0, 15));
EXPECT_EQ(1, GetDirection16(0, 0, 8, 15)); EXPECT_EQ(1, GetDirection16(0, 0, 8, 15));
EXPECT_EQ(0, GetDirection16(0, 0, 8, 8)); EXPECT_EQ(0, GetDirection16(0, 0, 8, 8));
EXPECT_EQ(15, GetDirection16(0, 0, 15, 8)); EXPECT_EQ(15, GetDirection16(0, 0, 15, 8));
EXPECT_EQ(15, GetDirection16(0, 0, 15, 7)); EXPECT_EQ(15, GetDirection16(0, 0, 15, 7));
EXPECT_EQ(15, GetDirection16(0, 0, 11, 7)); EXPECT_EQ(15, GetDirection16(0, 0, 11, 7));
EXPECT_EQ(0, GetDirection16(0, 0, 8, 11)); EXPECT_EQ(0, GetDirection16(0, 0, 8, 11));
EXPECT_EQ(8, GetDirection16(15, 15, 0, 0)); EXPECT_EQ(8, GetDirection16(15, 15, 0, 0));
EXPECT_EQ(10, GetDirection16(0, 15, 0, 0)); EXPECT_EQ(10, GetDirection16(0, 15, 0, 0));
EXPECT_EQ(9, GetDirection16(8, 15, 0, 0)); EXPECT_EQ(9, GetDirection16(8, 15, 0, 0));
EXPECT_EQ(8, GetDirection16(8, 8, 0, 0)); EXPECT_EQ(8, GetDirection16(8, 8, 0, 0));
EXPECT_EQ(7, GetDirection16(15, 8, 0, 0)); EXPECT_EQ(7, GetDirection16(15, 8, 0, 0));
EXPECT_EQ(7, GetDirection16(15, 7, 0, 0)); EXPECT_EQ(7, GetDirection16(15, 7, 0, 0));
EXPECT_EQ(7, GetDirection16(11, 7, 0, 0)); EXPECT_EQ(7, GetDirection16(11, 7, 0, 0));
EXPECT_EQ(8, GetDirection16(8, 11, 0, 0)); EXPECT_EQ(8, GetDirection16(8, 11, 0, 0));
EXPECT_EQ(12, GetDirection16(0, 15, 15, 0)); EXPECT_EQ(12, GetDirection16(0, 15, 15, 0));
EXPECT_EQ(14, GetDirection16(0, 0, 15, 0)); EXPECT_EQ(14, GetDirection16(0, 0, 15, 0));
EXPECT_EQ(13, GetDirection16(0, 8, 15, 0)); EXPECT_EQ(13, GetDirection16(0, 8, 15, 0));
EXPECT_EQ(12, GetDirection16(0, 8, 8, 0)); EXPECT_EQ(12, GetDirection16(0, 8, 8, 0));
EXPECT_EQ(11, GetDirection16(0, 15, 8, 0)); EXPECT_EQ(11, GetDirection16(0, 15, 8, 0));
EXPECT_EQ(11, GetDirection16(0, 15, 7, 0)); EXPECT_EQ(11, GetDirection16(0, 15, 7, 0));
EXPECT_EQ(11, GetDirection16(0, 11, 7, 0)); EXPECT_EQ(11, GetDirection16(0, 11, 7, 0));
EXPECT_EQ(12, GetDirection16(0, 8, 11, 0)); EXPECT_EQ(12, GetDirection16(0, 8, 11, 0));
EXPECT_EQ(0, GetDirection16(2, 2, 3, 3)); EXPECT_EQ(0, GetDirection16(2, 2, 3, 3));
EXPECT_EQ(1, GetDirection16(2, 2, 3, 4)); EXPECT_EQ(1, GetDirection16(2, 2, 3, 4));
EXPECT_EQ(2, GetDirection16(2, 2, 2, 4)); EXPECT_EQ(2, GetDirection16(2, 2, 2, 4));
EXPECT_EQ(3, GetDirection16(2, 2, 1, 4)); EXPECT_EQ(3, GetDirection16(2, 2, 1, 4));
EXPECT_EQ(4, GetDirection16(2, 2, 1, 3)); EXPECT_EQ(4, GetDirection16(2, 2, 1, 3));
EXPECT_EQ(5, GetDirection16(2, 2, 0, 3)); EXPECT_EQ(5, GetDirection16(2, 2, 0, 3));
EXPECT_EQ(6, GetDirection16(2, 2, 0, 2)); EXPECT_EQ(6, GetDirection16(2, 2, 0, 2));
EXPECT_EQ(7, GetDirection16(2, 2, 0, 1)); EXPECT_EQ(7, GetDirection16(2, 2, 0, 1));
EXPECT_EQ(8, GetDirection16(2, 2, 1, 1)); EXPECT_EQ(8, GetDirection16(2, 2, 1, 1));
EXPECT_EQ(9, GetDirection16(2, 2, 1, 0)); EXPECT_EQ(9, GetDirection16(2, 2, 1, 0));
EXPECT_EQ(10, GetDirection16(2, 2, 2, 0)); EXPECT_EQ(10, GetDirection16(2, 2, 2, 0));
EXPECT_EQ(11, GetDirection16(2, 2, 3, 0)); EXPECT_EQ(11, GetDirection16(2, 2, 3, 0));
EXPECT_EQ(12, GetDirection16(2, 2, 3, 1)); EXPECT_EQ(12, GetDirection16(2, 2, 3, 1));
EXPECT_EQ(13, GetDirection16(2, 2, 4, 1)); EXPECT_EQ(13, GetDirection16(2, 2, 4, 1));
EXPECT_EQ(14, GetDirection16(2, 2, 4, 2)); EXPECT_EQ(14, GetDirection16(2, 2, 4, 2));
EXPECT_EQ(15, GetDirection16(2, 2, 4, 3)); EXPECT_EQ(15, GetDirection16(2, 2, 4, 3));
} }

1212
test/pack_test.cpp

File diff suppressed because it is too large Load Diff

166
test/player_test.cpp

@ -1,83 +1,83 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "player.h" #include "player.h"
using namespace devilution; using namespace devilution;
namespace devilution { namespace devilution {
extern bool PM_DoGotHit(int pnum); extern bool PM_DoGotHit(int pnum);
} }
int RunBlockTest(int frames, int flags) int RunBlockTest(int frames, int flags)
{ {
int pnum = 0; int pnum = 0;
plr[pnum].AnimInfo.CurrentFrame = 1; plr[pnum].AnimInfo.CurrentFrame = 1;
plr[pnum]._pHFrames = frames; plr[pnum]._pHFrames = frames;
plr[pnum].actionFrame = 1; plr[pnum].actionFrame = 1;
plr[pnum]._pIFlags = flags; plr[pnum]._pIFlags = flags;
plr[pnum]._pmode = PM_GOTHIT; plr[pnum]._pmode = PM_GOTHIT;
plr[pnum]._pGFXLoad = -1; plr[pnum]._pGFXLoad = -1;
int i = 1; int i = 1;
for (; i < 100; i++) { for (; i < 100; i++) {
PM_DoGotHit(pnum); PM_DoGotHit(pnum);
if (plr[pnum]._pmode != PM_GOTHIT) if (plr[pnum]._pmode != PM_GOTHIT)
break; break;
plr[pnum].AnimInfo.CurrentFrame++; plr[pnum].AnimInfo.CurrentFrame++;
} }
return i; return i;
} }
#define NORM 0 #define NORM 0
#define BAL ISPL_FASTRECOVER #define BAL ISPL_FASTRECOVER
#define STA ISPL_FASTERRECOVER #define STA ISPL_FASTERRECOVER
#define HAR ISPL_FASTESTRECOVER #define HAR ISPL_FASTESTRECOVER
#define BALSTA (ISPL_FASTRECOVER | ISPL_FASTERRECOVER) #define BALSTA (ISPL_FASTRECOVER | ISPL_FASTERRECOVER)
#define BALHAR (ISPL_FASTRECOVER | ISPL_FASTESTRECOVER) #define BALHAR (ISPL_FASTRECOVER | ISPL_FASTESTRECOVER)
#define STAHAR (ISPL_FASTERRECOVER | ISPL_FASTESTRECOVER) #define STAHAR (ISPL_FASTERRECOVER | ISPL_FASTESTRECOVER)
#define ZEN (ISPL_FASTRECOVER | ISPL_FASTERRECOVER | ISPL_FASTESTRECOVER) #define ZEN (ISPL_FASTRECOVER | ISPL_FASTERRECOVER | ISPL_FASTESTRECOVER)
#define WAR 6 #define WAR 6
#define ROU 7 #define ROU 7
#define SRC 8 #define SRC 8
int BlockData[][3] = { int BlockData[][3] = {
{ 6, WAR, NORM }, { 6, WAR, NORM },
{ 7, ROU, NORM }, { 7, ROU, NORM },
{ 8, SRC, NORM }, { 8, SRC, NORM },
{ 5, WAR, BAL }, { 5, WAR, BAL },
{ 6, ROU, BAL }, { 6, ROU, BAL },
{ 7, SRC, BAL }, { 7, SRC, BAL },
{ 4, WAR, STA }, { 4, WAR, STA },
{ 5, ROU, STA }, { 5, ROU, STA },
{ 6, SRC, STA }, { 6, SRC, STA },
{ 3, WAR, HAR }, { 3, WAR, HAR },
{ 4, ROU, HAR }, { 4, ROU, HAR },
{ 5, SRC, HAR }, { 5, SRC, HAR },
{ 4, WAR, BALSTA }, { 4, WAR, BALSTA },
{ 5, ROU, BALSTA }, { 5, ROU, BALSTA },
{ 6, SRC, BALSTA }, { 6, SRC, BALSTA },
{ 3, WAR, BALHAR }, { 3, WAR, BALHAR },
{ 4, ROU, BALHAR }, { 4, ROU, BALHAR },
{ 5, SRC, BALHAR }, { 5, SRC, BALHAR },
{ 3, WAR, STAHAR }, { 3, WAR, STAHAR },
{ 4, ROU, STAHAR }, { 4, ROU, STAHAR },
{ 5, SRC, STAHAR }, { 5, SRC, STAHAR },
{ 2, WAR, ZEN }, { 2, WAR, ZEN },
{ 3, ROU, ZEN }, { 3, ROU, ZEN },
{ 4, SRC, ZEN }, { 4, SRC, ZEN },
}; };
TEST(Player, PM_DoGotHit) TEST(Player, PM_DoGotHit)
{ {
for (size_t i = 0; i < sizeof(BlockData) / sizeof(*BlockData); i++) { for (size_t i = 0; i < sizeof(BlockData) / sizeof(*BlockData); i++) {
EXPECT_EQ(BlockData[i][0], RunBlockTest(BlockData[i][1], BlockData[i][2])); EXPECT_EQ(BlockData[i][0], RunBlockTest(BlockData[i][1], BlockData[i][2]));
} }
} }

328
test/scrollrt_test.cpp

@ -1,164 +1,164 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "diablo.h" #include "diablo.h"
#include "scrollrt.h" #include "scrollrt.h"
#include "utils/ui_fwd.h" #include "utils/ui_fwd.h"
using namespace devilution; using namespace devilution;
// TilesInView // TilesInView
TEST(Scrool_rt, calc_tiles_in_view_original) TEST(Scrool_rt, calc_tiles_in_view_original)
{ {
gnScreenWidth = 640; gnScreenWidth = 640;
gnScreenHeight = 480; gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128; gnViewportHeight = gnScreenHeight - 128;
zoomflag = true; zoomflag = true;
int columns = 0; int columns = 0;
int rows = 0; int rows = 0;
TilesInView(&columns, &rows); TilesInView(&columns, &rows);
EXPECT_EQ(columns, 10); EXPECT_EQ(columns, 10);
EXPECT_EQ(rows, 11); EXPECT_EQ(rows, 11);
} }
TEST(Scrool_rt, calc_tiles_in_view_original_zoom) TEST(Scrool_rt, calc_tiles_in_view_original_zoom)
{ {
gnScreenWidth = 640; gnScreenWidth = 640;
gnScreenHeight = 480; gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128; gnViewportHeight = gnScreenHeight - 128;
zoomflag = false; zoomflag = false;
int columns = 0; int columns = 0;
int rows = 0; int rows = 0;
TilesInView(&columns, &rows); TilesInView(&columns, &rows);
EXPECT_EQ(columns, 5); EXPECT_EQ(columns, 5);
EXPECT_EQ(rows, 6); EXPECT_EQ(rows, 6);
} }
TEST(Scrool_rt, calc_tiles_in_view_960_540) TEST(Scrool_rt, calc_tiles_in_view_960_540)
{ {
gnScreenWidth = 960; gnScreenWidth = 960;
gnScreenHeight = 540; gnScreenHeight = 540;
gnViewportHeight = gnScreenHeight; gnViewportHeight = gnScreenHeight;
zoomflag = true; zoomflag = true;
int columns = 0; int columns = 0;
int rows = 0; int rows = 0;
TilesInView(&columns, &rows); TilesInView(&columns, &rows);
EXPECT_EQ(columns, 15); EXPECT_EQ(columns, 15);
EXPECT_EQ(rows, 17); EXPECT_EQ(rows, 17);
} }
TEST(Scrool_rt, calc_tiles_in_view_640_512) TEST(Scrool_rt, calc_tiles_in_view_640_512)
{ {
gnScreenWidth = 640; gnScreenWidth = 640;
gnScreenHeight = 512; gnScreenHeight = 512;
gnViewportHeight = gnScreenHeight - 128; gnViewportHeight = gnScreenHeight - 128;
zoomflag = true; zoomflag = true;
int columns = 0; int columns = 0;
int rows = 0; int rows = 0;
TilesInView(&columns, &rows); TilesInView(&columns, &rows);
EXPECT_EQ(columns, 10); EXPECT_EQ(columns, 10);
EXPECT_EQ(rows, 12); EXPECT_EQ(rows, 12);
} }
TEST(Scrool_rt, calc_tiles_in_view_768_480_zoom) TEST(Scrool_rt, calc_tiles_in_view_768_480_zoom)
{ {
gnScreenWidth = 768; gnScreenWidth = 768;
gnScreenHeight = 480; gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight; gnViewportHeight = gnScreenHeight;
zoomflag = false; zoomflag = false;
int columns = 0; int columns = 0;
int rows = 0; int rows = 0;
TilesInView(&columns, &rows); TilesInView(&columns, &rows);
EXPECT_EQ(columns, 6); EXPECT_EQ(columns, 6);
EXPECT_EQ(rows, 8); EXPECT_EQ(rows, 8);
} }
// CalcTileOffset // CalcTileOffset
TEST(Scrool_rt, calc_tile_offset_original) TEST(Scrool_rt, calc_tile_offset_original)
{ {
gnScreenWidth = 640; gnScreenWidth = 640;
gnScreenHeight = 480; gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128; gnViewportHeight = gnScreenHeight - 128;
zoomflag = true; zoomflag = true;
int x = 0; int x = 0;
int y = 0; int y = 0;
CalcTileOffset(&x, &y); CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0); EXPECT_EQ(x, 0);
EXPECT_EQ(y, 0); EXPECT_EQ(y, 0);
} }
TEST(Scrool_rt, calc_tile_offset_original_zoom) TEST(Scrool_rt, calc_tile_offset_original_zoom)
{ {
gnScreenWidth = 640; gnScreenWidth = 640;
gnScreenHeight = 480; gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128; gnViewportHeight = gnScreenHeight - 128;
zoomflag = false; zoomflag = false;
int x = 0; int x = 0;
int y = 0; int y = 0;
CalcTileOffset(&x, &y); CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0); EXPECT_EQ(x, 0);
EXPECT_EQ(y, 8); EXPECT_EQ(y, 8);
} }
TEST(Scrool_rt, calc_tile_offset_960_540) TEST(Scrool_rt, calc_tile_offset_960_540)
{ {
gnScreenWidth = 960; gnScreenWidth = 960;
gnScreenHeight = 540; gnScreenHeight = 540;
gnViewportHeight = gnScreenHeight; gnViewportHeight = gnScreenHeight;
zoomflag = true; zoomflag = true;
int x = 0; int x = 0;
int y = 0; int y = 0;
CalcTileOffset(&x, &y); CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0); EXPECT_EQ(x, 0);
EXPECT_EQ(y, 2); EXPECT_EQ(y, 2);
} }
TEST(Scrool_rt, calc_tile_offset_853_480) TEST(Scrool_rt, calc_tile_offset_853_480)
{ {
gnScreenWidth = 853; gnScreenWidth = 853;
gnScreenHeight = 480; gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight; gnViewportHeight = gnScreenHeight;
zoomflag = true; zoomflag = true;
int x = 0; int x = 0;
int y = 0; int y = 0;
CalcTileOffset(&x, &y); CalcTileOffset(&x, &y);
EXPECT_EQ(x, 21); EXPECT_EQ(x, 21);
EXPECT_EQ(y, 0); EXPECT_EQ(y, 0);
} }
TEST(Scrool_rt, calc_tile_offset_768_480_zoom) TEST(Scrool_rt, calc_tile_offset_768_480_zoom)
{ {
gnScreenWidth = 768; gnScreenWidth = 768;
gnScreenHeight = 480; gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight; gnViewportHeight = gnScreenHeight;
zoomflag = false; zoomflag = false;
int x = 0; int x = 0;
int y = 0; int y = 0;
CalcTileOffset(&x, &y); CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0); EXPECT_EQ(x, 0);
EXPECT_EQ(y, 8); EXPECT_EQ(y, 8);
} }
// RowsCoveredByPanel // RowsCoveredByPanel
TEST(Scrool_rt, calc_tiles_covered_by_panel_original) TEST(Scrool_rt, calc_tiles_covered_by_panel_original)
{ {
gnScreenWidth = 640; gnScreenWidth = 640;
zoomflag = true; zoomflag = true;
EXPECT_EQ(RowsCoveredByPanel(), 0); EXPECT_EQ(RowsCoveredByPanel(), 0);
} }
TEST(Scrool_rt, calc_tiles_covered_by_panel_960) TEST(Scrool_rt, calc_tiles_covered_by_panel_960)
{ {
gnScreenWidth = 960; gnScreenWidth = 960;
zoomflag = true; zoomflag = true;
EXPECT_EQ(RowsCoveredByPanel(), 4); EXPECT_EQ(RowsCoveredByPanel(), 4);
} }
TEST(Scrool_rt, calc_tiles_covered_by_panel_960_zoom) TEST(Scrool_rt, calc_tiles_covered_by_panel_960_zoom)
{ {
gnScreenWidth = 960; gnScreenWidth = 960;
zoomflag = false; zoomflag = false;
EXPECT_EQ(RowsCoveredByPanel(), 2); EXPECT_EQ(RowsCoveredByPanel(), 2);
} }

148
test/stores_test.cpp

@ -1,74 +1,74 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "stores.h" #include "stores.h"
using namespace devilution; using namespace devilution;
namespace { namespace {
TEST(Stores, AddStoreHoldRepair_magic) TEST(Stores, AddStoreHoldRepair_magic)
{ {
ItemStruct *item; ItemStruct *item;
item = &storehold[0]; item = &storehold[0];
item->_iMaxDur = 60; item->_iMaxDur = 60;
item->_iDurability = item->_iMaxDur; item->_iDurability = item->_iMaxDur;
item->_iMagical = ITEM_QUALITY_MAGIC; item->_iMagical = ITEM_QUALITY_MAGIC;
item->_iIdentified = true; item->_iIdentified = true;
item->_ivalue = 2000; item->_ivalue = 2000;
item->_iIvalue = 19000; item->_iIvalue = 19000;
for (int i = 1; i < item->_iMaxDur; i++) { for (int i = 1; i < item->_iMaxDur; i++) {
item->_ivalue = 2000; item->_ivalue = 2000;
item->_iIvalue = 19000; item->_iIvalue = 19000;
item->_iDurability = i; item->_iDurability = i;
storenumh = 0; storenumh = 0;
AddStoreHoldRepair(item, 0); AddStoreHoldRepair(item, 0);
EXPECT_EQ(1, storenumh); EXPECT_EQ(1, storenumh);
EXPECT_EQ(95 * (item->_iMaxDur - i) / 2, item->_ivalue); EXPECT_EQ(95 * (item->_iMaxDur - i) / 2, item->_ivalue);
} }
item->_iDurability = 59; item->_iDurability = 59;
storenumh = 0; storenumh = 0;
item->_ivalue = 500; item->_ivalue = 500;
item->_iIvalue = 30; // To cheap to repair item->_iIvalue = 30; // To cheap to repair
AddStoreHoldRepair(item, 0); AddStoreHoldRepair(item, 0);
EXPECT_EQ(0, storenumh); EXPECT_EQ(0, storenumh);
EXPECT_EQ(30, item->_iIvalue); EXPECT_EQ(30, item->_iIvalue);
EXPECT_EQ(500, item->_ivalue); EXPECT_EQ(500, item->_ivalue);
} }
TEST(Stores, AddStoreHoldRepair_normal) TEST(Stores, AddStoreHoldRepair_normal)
{ {
ItemStruct *item; ItemStruct *item;
item = &storehold[0]; item = &storehold[0];
item->_iMaxDur = 20; item->_iMaxDur = 20;
item->_iDurability = item->_iMaxDur; item->_iDurability = item->_iMaxDur;
item->_iMagical = ITEM_QUALITY_NORMAL; item->_iMagical = ITEM_QUALITY_NORMAL;
item->_iIdentified = true; item->_iIdentified = true;
item->_ivalue = 2000; item->_ivalue = 2000;
item->_iIvalue = item->_ivalue; item->_iIvalue = item->_ivalue;
for (int i = 1; i < item->_iMaxDur; i++) { for (int i = 1; i < item->_iMaxDur; i++) {
item->_ivalue = 2000; item->_ivalue = 2000;
item->_iIvalue = item->_ivalue; item->_iIvalue = item->_ivalue;
item->_iDurability = i; item->_iDurability = i;
storenumh = 0; storenumh = 0;
AddStoreHoldRepair(item, 0); AddStoreHoldRepair(item, 0);
EXPECT_EQ(1, storenumh); EXPECT_EQ(1, storenumh);
EXPECT_EQ(50 * (item->_iMaxDur - i), item->_ivalue); EXPECT_EQ(50 * (item->_iMaxDur - i), item->_ivalue);
} }
item->_iDurability = 19; item->_iDurability = 19;
storenumh = 0; storenumh = 0;
item->_ivalue = 10; // less then 1 per dur item->_ivalue = 10; // less then 1 per dur
item->_iIvalue = item->_ivalue; item->_iIvalue = item->_ivalue;
AddStoreHoldRepair(item, 0); AddStoreHoldRepair(item, 0);
EXPECT_EQ(1, storenumh); EXPECT_EQ(1, storenumh);
EXPECT_EQ(1, item->_ivalue); EXPECT_EQ(1, item->_ivalue);
EXPECT_EQ(1, item->_iIvalue); EXPECT_EQ(1, item->_iIvalue);
} }
} // namespace } // namespace

Loading…
Cancel
Save