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 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()
{

308
Source/engine/animationinfo.cpp

@ -1,154 +1,154 @@
/**
* @file animationinfo.cpp
*
* Contains the core animation information and related logic
*/
#include "animationinfo.h"
#include "appfat.h"
#include "nthread.h"
#include "utils/log.hpp"
namespace devilution {
int AnimationInfo::GetFrameToUseForRendering() const
{
// Normal logic is used,
// - if no frame-skipping is required and so we have exactly one Animationframe per game tick
// 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 (RelevantFramesForDistributing <= 0)
return CurrentFrame;
if (CurrentFrame > RelevantFramesForDistributing)
return CurrentFrame;
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.
float totalTicksForCurrentAnimationSequence = gfProgressToNextGameTick + (float)TicksSinceSequenceStarted;
// 1 added for rounding reasons. float to int cast always truncate.
int absoluteAnimationFrame = 1 + (int)(totalTicksForCurrentAnimationSequence * TickModifier);
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
absoluteAnimationFrame -= SkippedFramesFromPreviousAnimation;
if (absoluteAnimationFrame <= 0) {
// We still display the remains of the previous Animation
absoluteAnimationFrame = NumberOfFrames + absoluteAnimationFrame;
}
} else if (absoluteAnimationFrame > RelevantFramesForDistributing) {
// this can happen if we are at the last frame and the next game tick is due (gfProgressToNextGameTick >= 1.0f)
if (absoluteAnimationFrame > (RelevantFramesForDistributing + 1)) {
// we should never have +2 frames even if next game tick is due
Log("GetFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {} MaxFrame {})", absoluteAnimationFrame, RelevantFramesForDistributing);
}
return RelevantFramesForDistributing;
}
if (absoluteAnimationFrame <= 0) {
Log("GetFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {})", absoluteAnimationFrame);
return 1;
}
return absoluteAnimationFrame;
}
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) {
// 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.
SkippedFramesFromPreviousAnimation = NumberOfFrames - CurrentFrame;
} else {
SkippedFramesFromPreviousAnimation = 0;
}
this->pData = pData;
NumberOfFrames = numberOfFrames;
CurrentFrame = 1;
DelayCounter = 0;
DelayLen = delayLen;
TicksSinceSequenceStarted = 0;
RelevantFramesForDistributing = 0;
TickModifier = 0.0f;
if (numSkippedFrames != 0 || flags != AnimationDistributionFlags::None) {
// Animation Frames that will be adjusted for the skipped Frames/game ticks
int relevantAnimationFramesForDistributing = numberOfFrames;
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.
// 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).
// 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;
}
// How many game ticks are needed to advance one Animation Frame
int ticksPerFrame = (delayLen + 1);
// Game ticks that will be adjusted for the skipped Frames/game ticks
int relevantAnimationTicksForDistribution = relevantAnimationFramesForDistributing * ticksPerFrame;
// How many game ticks will the Animation be really shown (skipped Frames and game ticks removed)
int relevantAnimationTicksWithSkipping = relevantAnimationTicksForDistribution - (numSkippedFrames * ticksPerFrame);
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 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).
// Because of that, we only the remove one game tick from the time the Animation is shown
relevantAnimationTicksWithSkipping -= 1;
// 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.
// This also means Rendering should never hapen with TicksSinceSequenceStarted < 0.
TicksSinceSequenceStarted = -1;
}
if ((flags & AnimationDistributionFlags::SkipsDelayOfLastFrame) == AnimationDistributionFlags::SkipsDelayOfLastFrame) {
// 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
// Example:
// 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(); }"
// This will result that frame 4 is the last shown Animation Frame.
// GameTick Frame Cnt
// 1 1 0
// 2 1 1
// 3 2 0
// 3 2 1
// 4 3 0
// 5 - -
// 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.
// Thats why we need to remove the Delay of the last Frame from the time (game ticks) the Animation is shown
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)
relevantAnimationTicksForDistribution += (SkippedFramesFromPreviousAnimation * ticksPerFrame);
// 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;
// tickModifier specifies the Animation fraction per game tick, so we have to remove the delay from the variable
tickModifier /= ticksPerFrame;
RelevantFramesForDistributing = relevantAnimationFramesForDistributing;
TickModifier = tickModifier;
}
}
void AnimationInfo::ProcessAnimation()
{
DelayCounter++;
TicksSinceSequenceStarted++;
if (DelayCounter > DelayLen) {
DelayCounter = 0;
CurrentFrame++;
if (CurrentFrame > NumberOfFrames) {
CurrentFrame = 1;
TicksSinceSequenceStarted = 0;
}
}
}
} // namespace devilution
/**
* @file animationinfo.cpp
*
* Contains the core animation information and related logic
*/
#include "animationinfo.h"
#include "appfat.h"
#include "nthread.h"
#include "utils/log.hpp"
namespace devilution {
int AnimationInfo::GetFrameToUseForRendering() const
{
// Normal logic is used,
// - if no frame-skipping is required and so we have exactly one Animationframe per game tick
// 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 (RelevantFramesForDistributing <= 0)
return CurrentFrame;
if (CurrentFrame > RelevantFramesForDistributing)
return CurrentFrame;
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.
float totalTicksForCurrentAnimationSequence = gfProgressToNextGameTick + (float)TicksSinceSequenceStarted;
// 1 added for rounding reasons. float to int cast always truncate.
int absoluteAnimationFrame = 1 + (int)(totalTicksForCurrentAnimationSequence * TickModifier);
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
absoluteAnimationFrame -= SkippedFramesFromPreviousAnimation;
if (absoluteAnimationFrame <= 0) {
// We still display the remains of the previous Animation
absoluteAnimationFrame = NumberOfFrames + absoluteAnimationFrame;
}
} else if (absoluteAnimationFrame > RelevantFramesForDistributing) {
// this can happen if we are at the last frame and the next game tick is due (gfProgressToNextGameTick >= 1.0f)
if (absoluteAnimationFrame > (RelevantFramesForDistributing + 1)) {
// we should never have +2 frames even if next game tick is due
Log("GetFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {} MaxFrame {})", absoluteAnimationFrame, RelevantFramesForDistributing);
}
return RelevantFramesForDistributing;
}
if (absoluteAnimationFrame <= 0) {
Log("GetFrameToUseForRendering: Calculated an invalid Animation Frame (Calculated {})", absoluteAnimationFrame);
return 1;
}
return absoluteAnimationFrame;
}
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) {
// 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.
SkippedFramesFromPreviousAnimation = NumberOfFrames - CurrentFrame;
} else {
SkippedFramesFromPreviousAnimation = 0;
}
this->pData = pData;
NumberOfFrames = numberOfFrames;
CurrentFrame = 1;
DelayCounter = 0;
DelayLen = delayLen;
TicksSinceSequenceStarted = 0;
RelevantFramesForDistributing = 0;
TickModifier = 0.0f;
if (numSkippedFrames != 0 || flags != AnimationDistributionFlags::None) {
// Animation Frames that will be adjusted for the skipped Frames/game ticks
int relevantAnimationFramesForDistributing = numberOfFrames;
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.
// 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).
// 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;
}
// How many game ticks are needed to advance one Animation Frame
int ticksPerFrame = (delayLen + 1);
// Game ticks that will be adjusted for the skipped Frames/game ticks
int relevantAnimationTicksForDistribution = relevantAnimationFramesForDistributing * ticksPerFrame;
// How many game ticks will the Animation be really shown (skipped Frames and game ticks removed)
int relevantAnimationTicksWithSkipping = relevantAnimationTicksForDistribution - (numSkippedFrames * ticksPerFrame);
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 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).
// Because of that, we only the remove one game tick from the time the Animation is shown
relevantAnimationTicksWithSkipping -= 1;
// 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.
// This also means Rendering should never hapen with TicksSinceSequenceStarted < 0.
TicksSinceSequenceStarted = -1;
}
if ((flags & AnimationDistributionFlags::SkipsDelayOfLastFrame) == AnimationDistributionFlags::SkipsDelayOfLastFrame) {
// 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
// Example:
// 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(); }"
// This will result that frame 4 is the last shown Animation Frame.
// GameTick Frame Cnt
// 1 1 0
// 2 1 1
// 3 2 0
// 3 2 1
// 4 3 0
// 5 - -
// 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.
// Thats why we need to remove the Delay of the last Frame from the time (game ticks) the Animation is shown
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)
relevantAnimationTicksForDistribution += (SkippedFramesFromPreviousAnimation * ticksPerFrame);
// 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;
// tickModifier specifies the Animation fraction per game tick, so we have to remove the delay from the variable
tickModifier /= ticksPerFrame;
RelevantFramesForDistributing = relevantAnimationFramesForDistributing;
TickModifier = tickModifier;
}
}
void AnimationInfo::ProcessAnimation()
{
DelayCounter++;
TicksSinceSequenceStarted++;
if (DelayCounter > DelayLen) {
DelayCounter = 0;
CurrentFrame++;
if (CurrentFrame > NumberOfFrames) {
CurrentFrame = 1;
TicksSinceSequenceStarted = 0;
}
}
}
} // namespace devilution

202
Source/engine/animationinfo.h

@ -1,101 +1,101 @@
/**
* @file animationinfo.h
*
* Contains the core animation information and related logic
*/
#pragma once
#include <stdint.h>
#include <type_traits>
#include "engine.h"
namespace devilution {
/**
* @brief Specifies what special logics are applied for a Animation
*/
enum AnimationDistributionFlags : uint8_t {
None = 0,
/**
* @brief ProcessAnimation will be called after SetNewAnimation (in same game tick as NewPlrAnim)
*/
ProcessAnimationPending = 1 << 0,
/**
* @brief Delay of last Frame is ignored (for example, because only Frame and not delay is checked in game_logic)
*/
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)
*/
RepeatedAction = 1 << 2,
};
/*
* @brief Contains the core animation information and related logic
*/
class AnimationInfo {
public:
/**
* @brief Pointer to Animation Data
*/
byte *pData;
/**
* @brief Additional delay of each animation in the current animation
*/
int DelayLen;
/**
* @brief Increases by one each game tick, counting how close we are to DelayLen
*/
int DelayCounter;
/**
* @brief Number of frames in current animation
*/
int NumberOfFrames;
/**
* @brief Current frame of animation
*/
int CurrentFrame;
/**
* @brief Calculates the Frame to use for the Animation rendering
* @return The Frame to use for rendering
*/
int GetFrameToUseForRendering() const;
/**
* @brief Sets the new Animation with all relevant information for rendering
* @param pData Pointer to Animation Data
* @param numberOfFrames Number of Frames in Animation
* @param delayLen Delay after each Animation sequence
* @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 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);
/*
* @brief Process the Animation for a game tick (for example advances the frame)
*/
void ProcessAnimation();
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).
*/
float TickModifier;
/**
* @brief Number of game ticks after the current animation sequence started
*/
int TicksSinceSequenceStarted;
/**
* @brief Animation Frames that will be adjusted for the skipped Frames/game ticks
*/
int RelevantFramesForDistributing;
/**
* @brief Animation Frames that wasn't shown from previous Animation
*/
int SkippedFramesFromPreviousAnimation;
};
} // namespace devilution
/**
* @file animationinfo.h
*
* Contains the core animation information and related logic
*/
#pragma once
#include <stdint.h>
#include <type_traits>
#include "engine.h"
namespace devilution {
/**
* @brief Specifies what special logics are applied for a Animation
*/
enum AnimationDistributionFlags : uint8_t {
None = 0,
/**
* @brief ProcessAnimation will be called after SetNewAnimation (in same game tick as NewPlrAnim)
*/
ProcessAnimationPending = 1 << 0,
/**
* @brief Delay of last Frame is ignored (for example, because only Frame and not delay is checked in game_logic)
*/
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)
*/
RepeatedAction = 1 << 2,
};
/*
* @brief Contains the core animation information and related logic
*/
class AnimationInfo {
public:
/**
* @brief Pointer to Animation Data
*/
byte *pData;
/**
* @brief Additional delay of each animation in the current animation
*/
int DelayLen;
/**
* @brief Increases by one each game tick, counting how close we are to DelayLen
*/
int DelayCounter;
/**
* @brief Number of frames in current animation
*/
int NumberOfFrames;
/**
* @brief Current frame of animation
*/
int CurrentFrame;
/**
* @brief Calculates the Frame to use for the Animation rendering
* @return The Frame to use for rendering
*/
int GetFrameToUseForRendering() const;
/**
* @brief Sets the new Animation with all relevant information for rendering
* @param pData Pointer to Animation Data
* @param numberOfFrames Number of Frames in Animation
* @param delayLen Delay after each Animation sequence
* @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 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);
/*
* @brief Process the Animation for a game tick (for example advances the frame)
*/
void ProcessAnimation();
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).
*/
float TickModifier;
/**
* @brief Number of game ticks after the current animation sequence started
*/
int TicksSinceSequenceStarted;
/**
* @brief Animation Frames that will be adjusted for the skipped Frames/game ticks
*/
int RelevantFramesForDistributing;
/**
* @brief Animation Frames that wasn't shown from previous Animation
*/
int SkippedFramesFromPreviousAnimation;
};
} // namespace devilution

10
Source/storm/storm_dvlnet.h

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

146
Source/utils/math.h

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

38
Source/utils/stdcompat/string_view.hpp

@ -1,19 +1,19 @@
#pragma once
#ifdef __has_include
#if defined(__cplusplus) && __cplusplus >= 201703L && __has_include(<string_view>) // should be 201606L, but STL headers disagree
#include <string_view> // IWYU pragma: export
namespace devilution {
using string_view = std::string_view;
}
#elif __has_include(<experimental/string_view>)
#include <experimental/string_view> // IWYU pragma: export
namespace devilution {
using string_view = std::experimental::string_view;
}
#else
#error "Missing support for <string_view> or <experimental/string_view>"
#endif
#else
#error "__has_include unavailable"
#endif
#pragma once
#ifdef __has_include
#if defined(__cplusplus) && __cplusplus >= 201703L && __has_include(<string_view>) // should be 201606L, but STL headers disagree
#include <string_view> // IWYU pragma: export
namespace devilution {
using string_view = std::string_view;
}
#elif __has_include(<experimental/string_view>)
#include <experimental/string_view> // IWYU pragma: export
namespace devilution {
using string_view = std::experimental::string_view;
}
#else
#error "Missing support for <string_view> or <experimental/string_view>"
#endif
#else
#error "__has_include unavailable"
#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 "appfat.h"
#include "diablo.h"
using namespace devilution;
TEST(Appfat, app_fatal)
{
EXPECT_EXIT(app_fatal("test"), ::testing::ExitedWithCode(1), "test");
}
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");
}
TEST(Appfat, FileErrDlg)
{
EXPECT_EXIT(FileErrDlg("devilution/image.cl2"), ::testing::ExitedWithCode(1), "devilution/image.cl2");
}
TEST(Appfat, InsertCDDlg)
{
EXPECT_EXIT(InsertCDDlg(), ::testing::ExitedWithCode(1), "diabdat.mpq");
}
TEST(Appfat, DirErrorDlg)
{
EXPECT_EXIT(DirErrorDlg("/"), ::testing::ExitedWithCode(1), "Unable to write to location:\n/");
}
#include <gtest/gtest.h>
#include "appfat.h"
#include "diablo.h"
using namespace devilution;
TEST(Appfat, app_fatal)
{
EXPECT_EXIT(app_fatal("test"), ::testing::ExitedWithCode(1), "test");
}
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");
}
TEST(Appfat, FileErrDlg)
{
EXPECT_EXIT(FileErrDlg("devilution/image.cl2"), ::testing::ExitedWithCode(1), "devilution/image.cl2");
}
TEST(Appfat, InsertCDDlg)
{
EXPECT_EXIT(InsertCDDlg(), ::testing::ExitedWithCode(1), "diabdat.mpq");
}
TEST(Appfat, DirErrorDlg)
{
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 "automap.h"
using namespace devilution;
TEST(Automap, InitAutomap)
{
InitAutomapOnce();
EXPECT_EQ(AutomapActive, false);
EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16);
EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2);
}
TEST(Automap, StartAutomap)
{
StartAutomap();
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0);
EXPECT_EQ(AutomapActive, true);
}
TEST(Automap, AutomapUp)
{
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapUp();
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0);
}
TEST(Automap, AutomapDown)
{
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapDown();
EXPECT_EQ(AutomapOffset.x, 2);
EXPECT_EQ(AutomapOffset.y, 2);
}
TEST(Automap, AutomapLeft)
{
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapLeft();
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 2);
}
TEST(Automap, AutomapRight)
{
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapRight();
EXPECT_EQ(AutomapOffset.x, 2);
EXPECT_EQ(AutomapOffset.y, 0);
}
TEST(Automap, AutomapZoomIn)
{
AutoMapScale = 50;
AutomapZoomIn();
EXPECT_EQ(AutoMapScale, 55);
EXPECT_EQ(AmLine64, 35);
EXPECT_EQ(AmLine32, 17);
EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2);
}
TEST(Automap, AutomapZoomIn_Max)
{
AutoMapScale = 195;
AutomapZoomIn();
AutomapZoomIn();
EXPECT_EQ(AutoMapScale, 200);
EXPECT_EQ(AmLine64, 128);
EXPECT_EQ(AmLine32, 64);
EXPECT_EQ(AmLine16, 32);
EXPECT_EQ(AmLine8, 16);
EXPECT_EQ(AmLine4, 8);
}
TEST(Automap, AutomapZoomOut)
{
AutoMapScale = 200;
AutomapZoomOut();
EXPECT_EQ(AutoMapScale, 195);
EXPECT_EQ(AmLine64, 124);
EXPECT_EQ(AmLine32, 62);
EXPECT_EQ(AmLine16, 31);
EXPECT_EQ(AmLine8, 15);
EXPECT_EQ(AmLine4, 7);
}
TEST(Automap, AutomapZoomOut_Min)
{
AutoMapScale = 55;
AutomapZoomOut();
AutomapZoomOut();
EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16);
EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2);
}
TEST(Automap, AutomapZoomReset)
{
AutoMapScale = 50;
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapZoomReset();
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0);
EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16);
EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2);
}
#include <gtest/gtest.h>
#include "automap.h"
using namespace devilution;
TEST(Automap, InitAutomap)
{
InitAutomapOnce();
EXPECT_EQ(AutomapActive, false);
EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16);
EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2);
}
TEST(Automap, StartAutomap)
{
StartAutomap();
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0);
EXPECT_EQ(AutomapActive, true);
}
TEST(Automap, AutomapUp)
{
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapUp();
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0);
}
TEST(Automap, AutomapDown)
{
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapDown();
EXPECT_EQ(AutomapOffset.x, 2);
EXPECT_EQ(AutomapOffset.y, 2);
}
TEST(Automap, AutomapLeft)
{
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapLeft();
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 2);
}
TEST(Automap, AutomapRight)
{
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapRight();
EXPECT_EQ(AutomapOffset.x, 2);
EXPECT_EQ(AutomapOffset.y, 0);
}
TEST(Automap, AutomapZoomIn)
{
AutoMapScale = 50;
AutomapZoomIn();
EXPECT_EQ(AutoMapScale, 55);
EXPECT_EQ(AmLine64, 35);
EXPECT_EQ(AmLine32, 17);
EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2);
}
TEST(Automap, AutomapZoomIn_Max)
{
AutoMapScale = 195;
AutomapZoomIn();
AutomapZoomIn();
EXPECT_EQ(AutoMapScale, 200);
EXPECT_EQ(AmLine64, 128);
EXPECT_EQ(AmLine32, 64);
EXPECT_EQ(AmLine16, 32);
EXPECT_EQ(AmLine8, 16);
EXPECT_EQ(AmLine4, 8);
}
TEST(Automap, AutomapZoomOut)
{
AutoMapScale = 200;
AutomapZoomOut();
EXPECT_EQ(AutoMapScale, 195);
EXPECT_EQ(AmLine64, 124);
EXPECT_EQ(AmLine32, 62);
EXPECT_EQ(AmLine16, 31);
EXPECT_EQ(AmLine8, 15);
EXPECT_EQ(AmLine4, 7);
}
TEST(Automap, AutomapZoomOut_Min)
{
AutoMapScale = 55;
AutomapZoomOut();
AutomapZoomOut();
EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16);
EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2);
}
TEST(Automap, AutomapZoomReset)
{
AutoMapScale = 50;
AutomapOffset.x = 1;
AutomapOffset.y = 1;
AutomapZoomReset();
EXPECT_EQ(AutomapOffset.x, 0);
EXPECT_EQ(AutomapOffset.y, 0);
EXPECT_EQ(AutoMapScale, 50);
EXPECT_EQ(AmLine64, 32);
EXPECT_EQ(AmLine32, 16);
EXPECT_EQ(AmLine16, 8);
EXPECT_EQ(AmLine8, 4);
EXPECT_EQ(AmLine4, 2);
}

30
test/codec_test.cpp

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

58
test/control_test.cpp

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

38
test/cursor_test.cpp

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

38
test/dead_test.cpp

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

28
test/diablo_test.cpp

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

34
test/doom_test.cpp

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

42
test/drlg_l1_test.cpp

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

24
test/drlg_l2_test.cpp

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

70
test/drlg_l3_test.cpp

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

42
test/drlg_l4_test.cpp

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

112
test/effects_test.cpp

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

452
test/inv_test.cpp

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

76
test/lighting_test.cpp

@ -1,38 +1,38 @@
#include <gtest/gtest.h>
#include "control.h"
#include "lighting.h"
using namespace devilution;
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 };
bool added[40][40];
memset(added, 0, sizeof(added));
for (int j = 0; j < 19; j++) {
int x = 20;
int y = 20;
int cr = CrawlNum[j] + 1;
for (unsigned i = (uint8_t)CrawlTable[cr - 1]; i > 0; i--, cr += 2) {
int dx = x + CrawlTable[cr];
int dy = y + CrawlTable[cr + 1];
sprintf(tempstr, "location %d:%d added twice.", dx - 20, dy - 20);
EXPECT_EQ(added[dx][dy], false) << tempstr;
added[dx][dy] = true;
}
}
for (int i = -18; i <= 18; i++) {
for (int j = -18; j <= 18; j++) {
if (added[i + 20][j + 20])
continue;
if ((i == -18 && j == -18) || (i == -18 && j == 18) || (i == 18 && j == -18) || (i == 18 && j == 18))
continue; // Limit of the crawl table rage
sprintf(tempstr, "while checking location %d:%d.", i, j);
EXPECT_EQ(false, true) << tempstr;
}
}
}
#include <gtest/gtest.h>
#include "control.h"
#include "lighting.h"
using namespace devilution;
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 };
bool added[40][40];
memset(added, 0, sizeof(added));
for (int j = 0; j < 19; j++) {
int x = 20;
int y = 20;
int cr = CrawlNum[j] + 1;
for (unsigned i = (uint8_t)CrawlTable[cr - 1]; i > 0; i--, cr += 2) {
int dx = x + CrawlTable[cr];
int dy = y + CrawlTable[cr + 1];
sprintf(tempstr, "location %d:%d added twice.", dx - 20, dy - 20);
EXPECT_EQ(added[dx][dy], false) << tempstr;
added[dx][dy] = true;
}
}
for (int i = -18; i <= 18; i++) {
for (int j = -18; j <= 18; j++) {
if (added[i + 20][j + 20])
continue;
if ((i == -18 && j == -18) || (i == -18 && j == 18) || (i == 18 && j == -18) || (i == 18 && j == 18))
continue; // Limit of the crawl table rage
sprintf(tempstr, "while checking location %d:%d.", i, j);
EXPECT_EQ(false, true) << tempstr;
}
}
}

174
test/missiles_test.cpp

@ -1,87 +1,87 @@
#include <gtest/gtest.h>
#include "missiles.h"
using namespace devilution;
TEST(Missiles, GetDirection8)
{
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 15 }));
EXPECT_EQ(1, GetDirection({ 0, 0 }, { 0, 15 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 15 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 8 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 8 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 7 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 11, 7 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 11 }));
EXPECT_EQ(4, GetDirection({ 15, 15 }, { 0, 0 }));
EXPECT_EQ(5, GetDirection({ 0, 15 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 8, 15 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 8, 8 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 15, 8 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 15, 7 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 11, 7 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 8, 11 }, { 0, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 15 }, { 15, 0 }));
EXPECT_EQ(7, GetDirection({ 0, 0 }, { 15, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 8 }, { 15, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 8 }, { 8, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 15 }, { 8, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 15 }, { 7, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 11 }, { 7, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 8 }, { 11, 0 }));
EXPECT_EQ(0, GetDirection({ 1, 1 }, { 2, 2 }));
EXPECT_EQ(1, GetDirection({ 1, 1 }, { 1, 2 }));
EXPECT_EQ(2, GetDirection({ 1, 1 }, { 0, 2 }));
EXPECT_EQ(3, GetDirection({ 1, 1 }, { 0, 1 }));
EXPECT_EQ(4, GetDirection({ 1, 1 }, { 0, 0 }));
EXPECT_EQ(5, GetDirection({ 1, 1 }, { 1, 0 }));
EXPECT_EQ(6, GetDirection({ 1, 1 }, { 2, 0 }));
EXPECT_EQ(7, GetDirection({ 1, 1 }, { 2, 1 }));
}
TEST(Missiles, GetDirection16)
{
EXPECT_EQ(0, GetDirection16(0, 0, 15, 15));
EXPECT_EQ(2, GetDirection16(0, 0, 0, 15));
EXPECT_EQ(1, GetDirection16(0, 0, 8, 15));
EXPECT_EQ(0, GetDirection16(0, 0, 8, 8));
EXPECT_EQ(15, GetDirection16(0, 0, 15, 8));
EXPECT_EQ(15, GetDirection16(0, 0, 15, 7));
EXPECT_EQ(15, GetDirection16(0, 0, 11, 7));
EXPECT_EQ(0, GetDirection16(0, 0, 8, 11));
EXPECT_EQ(8, GetDirection16(15, 15, 0, 0));
EXPECT_EQ(10, GetDirection16(0, 15, 0, 0));
EXPECT_EQ(9, GetDirection16(8, 15, 0, 0));
EXPECT_EQ(8, GetDirection16(8, 8, 0, 0));
EXPECT_EQ(7, GetDirection16(15, 8, 0, 0));
EXPECT_EQ(7, GetDirection16(15, 7, 0, 0));
EXPECT_EQ(7, GetDirection16(11, 7, 0, 0));
EXPECT_EQ(8, GetDirection16(8, 11, 0, 0));
EXPECT_EQ(12, GetDirection16(0, 15, 15, 0));
EXPECT_EQ(14, GetDirection16(0, 0, 15, 0));
EXPECT_EQ(13, GetDirection16(0, 8, 15, 0));
EXPECT_EQ(12, GetDirection16(0, 8, 8, 0));
EXPECT_EQ(11, GetDirection16(0, 15, 8, 0));
EXPECT_EQ(11, GetDirection16(0, 15, 7, 0));
EXPECT_EQ(11, GetDirection16(0, 11, 7, 0));
EXPECT_EQ(12, GetDirection16(0, 8, 11, 0));
EXPECT_EQ(0, GetDirection16(2, 2, 3, 3));
EXPECT_EQ(1, GetDirection16(2, 2, 3, 4));
EXPECT_EQ(2, GetDirection16(2, 2, 2, 4));
EXPECT_EQ(3, GetDirection16(2, 2, 1, 4));
EXPECT_EQ(4, GetDirection16(2, 2, 1, 3));
EXPECT_EQ(5, GetDirection16(2, 2, 0, 3));
EXPECT_EQ(6, GetDirection16(2, 2, 0, 2));
EXPECT_EQ(7, GetDirection16(2, 2, 0, 1));
EXPECT_EQ(8, GetDirection16(2, 2, 1, 1));
EXPECT_EQ(9, GetDirection16(2, 2, 1, 0));
EXPECT_EQ(10, GetDirection16(2, 2, 2, 0));
EXPECT_EQ(11, GetDirection16(2, 2, 3, 0));
EXPECT_EQ(12, GetDirection16(2, 2, 3, 1));
EXPECT_EQ(13, GetDirection16(2, 2, 4, 1));
EXPECT_EQ(14, GetDirection16(2, 2, 4, 2));
EXPECT_EQ(15, GetDirection16(2, 2, 4, 3));
}
#include <gtest/gtest.h>
#include "missiles.h"
using namespace devilution;
TEST(Missiles, GetDirection8)
{
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 15 }));
EXPECT_EQ(1, GetDirection({ 0, 0 }, { 0, 15 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 15 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 8 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 8 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 15, 7 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 11, 7 }));
EXPECT_EQ(0, GetDirection({ 0, 0 }, { 8, 11 }));
EXPECT_EQ(4, GetDirection({ 15, 15 }, { 0, 0 }));
EXPECT_EQ(5, GetDirection({ 0, 15 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 8, 15 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 8, 8 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 15, 8 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 15, 7 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 11, 7 }, { 0, 0 }));
EXPECT_EQ(4, GetDirection({ 8, 11 }, { 0, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 15 }, { 15, 0 }));
EXPECT_EQ(7, GetDirection({ 0, 0 }, { 15, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 8 }, { 15, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 8 }, { 8, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 15 }, { 8, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 15 }, { 7, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 11 }, { 7, 0 }));
EXPECT_EQ(6, GetDirection({ 0, 8 }, { 11, 0 }));
EXPECT_EQ(0, GetDirection({ 1, 1 }, { 2, 2 }));
EXPECT_EQ(1, GetDirection({ 1, 1 }, { 1, 2 }));
EXPECT_EQ(2, GetDirection({ 1, 1 }, { 0, 2 }));
EXPECT_EQ(3, GetDirection({ 1, 1 }, { 0, 1 }));
EXPECT_EQ(4, GetDirection({ 1, 1 }, { 0, 0 }));
EXPECT_EQ(5, GetDirection({ 1, 1 }, { 1, 0 }));
EXPECT_EQ(6, GetDirection({ 1, 1 }, { 2, 0 }));
EXPECT_EQ(7, GetDirection({ 1, 1 }, { 2, 1 }));
}
TEST(Missiles, GetDirection16)
{
EXPECT_EQ(0, GetDirection16(0, 0, 15, 15));
EXPECT_EQ(2, GetDirection16(0, 0, 0, 15));
EXPECT_EQ(1, GetDirection16(0, 0, 8, 15));
EXPECT_EQ(0, GetDirection16(0, 0, 8, 8));
EXPECT_EQ(15, GetDirection16(0, 0, 15, 8));
EXPECT_EQ(15, GetDirection16(0, 0, 15, 7));
EXPECT_EQ(15, GetDirection16(0, 0, 11, 7));
EXPECT_EQ(0, GetDirection16(0, 0, 8, 11));
EXPECT_EQ(8, GetDirection16(15, 15, 0, 0));
EXPECT_EQ(10, GetDirection16(0, 15, 0, 0));
EXPECT_EQ(9, GetDirection16(8, 15, 0, 0));
EXPECT_EQ(8, GetDirection16(8, 8, 0, 0));
EXPECT_EQ(7, GetDirection16(15, 8, 0, 0));
EXPECT_EQ(7, GetDirection16(15, 7, 0, 0));
EXPECT_EQ(7, GetDirection16(11, 7, 0, 0));
EXPECT_EQ(8, GetDirection16(8, 11, 0, 0));
EXPECT_EQ(12, GetDirection16(0, 15, 15, 0));
EXPECT_EQ(14, GetDirection16(0, 0, 15, 0));
EXPECT_EQ(13, GetDirection16(0, 8, 15, 0));
EXPECT_EQ(12, GetDirection16(0, 8, 8, 0));
EXPECT_EQ(11, GetDirection16(0, 15, 8, 0));
EXPECT_EQ(11, GetDirection16(0, 15, 7, 0));
EXPECT_EQ(11, GetDirection16(0, 11, 7, 0));
EXPECT_EQ(12, GetDirection16(0, 8, 11, 0));
EXPECT_EQ(0, GetDirection16(2, 2, 3, 3));
EXPECT_EQ(1, GetDirection16(2, 2, 3, 4));
EXPECT_EQ(2, GetDirection16(2, 2, 2, 4));
EXPECT_EQ(3, GetDirection16(2, 2, 1, 4));
EXPECT_EQ(4, GetDirection16(2, 2, 1, 3));
EXPECT_EQ(5, GetDirection16(2, 2, 0, 3));
EXPECT_EQ(6, GetDirection16(2, 2, 0, 2));
EXPECT_EQ(7, GetDirection16(2, 2, 0, 1));
EXPECT_EQ(8, GetDirection16(2, 2, 1, 1));
EXPECT_EQ(9, GetDirection16(2, 2, 1, 0));
EXPECT_EQ(10, GetDirection16(2, 2, 2, 0));
EXPECT_EQ(11, GetDirection16(2, 2, 3, 0));
EXPECT_EQ(12, GetDirection16(2, 2, 3, 1));
EXPECT_EQ(13, GetDirection16(2, 2, 4, 1));
EXPECT_EQ(14, GetDirection16(2, 2, 4, 2));
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 "player.h"
using namespace devilution;
namespace devilution {
extern bool PM_DoGotHit(int pnum);
}
int RunBlockTest(int frames, int flags)
{
int pnum = 0;
plr[pnum].AnimInfo.CurrentFrame = 1;
plr[pnum]._pHFrames = frames;
plr[pnum].actionFrame = 1;
plr[pnum]._pIFlags = flags;
plr[pnum]._pmode = PM_GOTHIT;
plr[pnum]._pGFXLoad = -1;
int i = 1;
for (; i < 100; i++) {
PM_DoGotHit(pnum);
if (plr[pnum]._pmode != PM_GOTHIT)
break;
plr[pnum].AnimInfo.CurrentFrame++;
}
return i;
}
#define NORM 0
#define BAL ISPL_FASTRECOVER
#define STA ISPL_FASTERRECOVER
#define HAR ISPL_FASTESTRECOVER
#define BALSTA (ISPL_FASTRECOVER | ISPL_FASTERRECOVER)
#define BALHAR (ISPL_FASTRECOVER | ISPL_FASTESTRECOVER)
#define STAHAR (ISPL_FASTERRECOVER | ISPL_FASTESTRECOVER)
#define ZEN (ISPL_FASTRECOVER | ISPL_FASTERRECOVER | ISPL_FASTESTRECOVER)
#define WAR 6
#define ROU 7
#define SRC 8
int BlockData[][3] = {
{ 6, WAR, NORM },
{ 7, ROU, NORM },
{ 8, SRC, NORM },
{ 5, WAR, BAL },
{ 6, ROU, BAL },
{ 7, SRC, BAL },
{ 4, WAR, STA },
{ 5, ROU, STA },
{ 6, SRC, STA },
{ 3, WAR, HAR },
{ 4, ROU, HAR },
{ 5, SRC, HAR },
{ 4, WAR, BALSTA },
{ 5, ROU, BALSTA },
{ 6, SRC, BALSTA },
{ 3, WAR, BALHAR },
{ 4, ROU, BALHAR },
{ 5, SRC, BALHAR },
{ 3, WAR, STAHAR },
{ 4, ROU, STAHAR },
{ 5, SRC, STAHAR },
{ 2, WAR, ZEN },
{ 3, ROU, ZEN },
{ 4, SRC, ZEN },
};
TEST(Player, PM_DoGotHit)
{
for (size_t i = 0; i < sizeof(BlockData) / sizeof(*BlockData); i++) {
EXPECT_EQ(BlockData[i][0], RunBlockTest(BlockData[i][1], BlockData[i][2]));
}
}
#include <gtest/gtest.h>
#include "player.h"
using namespace devilution;
namespace devilution {
extern bool PM_DoGotHit(int pnum);
}
int RunBlockTest(int frames, int flags)
{
int pnum = 0;
plr[pnum].AnimInfo.CurrentFrame = 1;
plr[pnum]._pHFrames = frames;
plr[pnum].actionFrame = 1;
plr[pnum]._pIFlags = flags;
plr[pnum]._pmode = PM_GOTHIT;
plr[pnum]._pGFXLoad = -1;
int i = 1;
for (; i < 100; i++) {
PM_DoGotHit(pnum);
if (plr[pnum]._pmode != PM_GOTHIT)
break;
plr[pnum].AnimInfo.CurrentFrame++;
}
return i;
}
#define NORM 0
#define BAL ISPL_FASTRECOVER
#define STA ISPL_FASTERRECOVER
#define HAR ISPL_FASTESTRECOVER
#define BALSTA (ISPL_FASTRECOVER | ISPL_FASTERRECOVER)
#define BALHAR (ISPL_FASTRECOVER | ISPL_FASTESTRECOVER)
#define STAHAR (ISPL_FASTERRECOVER | ISPL_FASTESTRECOVER)
#define ZEN (ISPL_FASTRECOVER | ISPL_FASTERRECOVER | ISPL_FASTESTRECOVER)
#define WAR 6
#define ROU 7
#define SRC 8
int BlockData[][3] = {
{ 6, WAR, NORM },
{ 7, ROU, NORM },
{ 8, SRC, NORM },
{ 5, WAR, BAL },
{ 6, ROU, BAL },
{ 7, SRC, BAL },
{ 4, WAR, STA },
{ 5, ROU, STA },
{ 6, SRC, STA },
{ 3, WAR, HAR },
{ 4, ROU, HAR },
{ 5, SRC, HAR },
{ 4, WAR, BALSTA },
{ 5, ROU, BALSTA },
{ 6, SRC, BALSTA },
{ 3, WAR, BALHAR },
{ 4, ROU, BALHAR },
{ 5, SRC, BALHAR },
{ 3, WAR, STAHAR },
{ 4, ROU, STAHAR },
{ 5, SRC, STAHAR },
{ 2, WAR, ZEN },
{ 3, ROU, ZEN },
{ 4, SRC, ZEN },
};
TEST(Player, PM_DoGotHit)
{
for (size_t i = 0; i < sizeof(BlockData) / sizeof(*BlockData); i++) {
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 "diablo.h"
#include "scrollrt.h"
#include "utils/ui_fwd.h"
using namespace devilution;
// TilesInView
TEST(Scrool_rt, calc_tiles_in_view_original)
{
gnScreenWidth = 640;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = true;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 10);
EXPECT_EQ(rows, 11);
}
TEST(Scrool_rt, calc_tiles_in_view_original_zoom)
{
gnScreenWidth = 640;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = false;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 5);
EXPECT_EQ(rows, 6);
}
TEST(Scrool_rt, calc_tiles_in_view_960_540)
{
gnScreenWidth = 960;
gnScreenHeight = 540;
gnViewportHeight = gnScreenHeight;
zoomflag = true;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 15);
EXPECT_EQ(rows, 17);
}
TEST(Scrool_rt, calc_tiles_in_view_640_512)
{
gnScreenWidth = 640;
gnScreenHeight = 512;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = true;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 10);
EXPECT_EQ(rows, 12);
}
TEST(Scrool_rt, calc_tiles_in_view_768_480_zoom)
{
gnScreenWidth = 768;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight;
zoomflag = false;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 6);
EXPECT_EQ(rows, 8);
}
// CalcTileOffset
TEST(Scrool_rt, calc_tile_offset_original)
{
gnScreenWidth = 640;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = true;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 0);
}
TEST(Scrool_rt, calc_tile_offset_original_zoom)
{
gnScreenWidth = 640;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = false;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 8);
}
TEST(Scrool_rt, calc_tile_offset_960_540)
{
gnScreenWidth = 960;
gnScreenHeight = 540;
gnViewportHeight = gnScreenHeight;
zoomflag = true;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 2);
}
TEST(Scrool_rt, calc_tile_offset_853_480)
{
gnScreenWidth = 853;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight;
zoomflag = true;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 21);
EXPECT_EQ(y, 0);
}
TEST(Scrool_rt, calc_tile_offset_768_480_zoom)
{
gnScreenWidth = 768;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight;
zoomflag = false;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 8);
}
// RowsCoveredByPanel
TEST(Scrool_rt, calc_tiles_covered_by_panel_original)
{
gnScreenWidth = 640;
zoomflag = true;
EXPECT_EQ(RowsCoveredByPanel(), 0);
}
TEST(Scrool_rt, calc_tiles_covered_by_panel_960)
{
gnScreenWidth = 960;
zoomflag = true;
EXPECT_EQ(RowsCoveredByPanel(), 4);
}
TEST(Scrool_rt, calc_tiles_covered_by_panel_960_zoom)
{
gnScreenWidth = 960;
zoomflag = false;
EXPECT_EQ(RowsCoveredByPanel(), 2);
}
#include <gtest/gtest.h>
#include "diablo.h"
#include "scrollrt.h"
#include "utils/ui_fwd.h"
using namespace devilution;
// TilesInView
TEST(Scrool_rt, calc_tiles_in_view_original)
{
gnScreenWidth = 640;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = true;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 10);
EXPECT_EQ(rows, 11);
}
TEST(Scrool_rt, calc_tiles_in_view_original_zoom)
{
gnScreenWidth = 640;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = false;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 5);
EXPECT_EQ(rows, 6);
}
TEST(Scrool_rt, calc_tiles_in_view_960_540)
{
gnScreenWidth = 960;
gnScreenHeight = 540;
gnViewportHeight = gnScreenHeight;
zoomflag = true;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 15);
EXPECT_EQ(rows, 17);
}
TEST(Scrool_rt, calc_tiles_in_view_640_512)
{
gnScreenWidth = 640;
gnScreenHeight = 512;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = true;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 10);
EXPECT_EQ(rows, 12);
}
TEST(Scrool_rt, calc_tiles_in_view_768_480_zoom)
{
gnScreenWidth = 768;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight;
zoomflag = false;
int columns = 0;
int rows = 0;
TilesInView(&columns, &rows);
EXPECT_EQ(columns, 6);
EXPECT_EQ(rows, 8);
}
// CalcTileOffset
TEST(Scrool_rt, calc_tile_offset_original)
{
gnScreenWidth = 640;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = true;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 0);
}
TEST(Scrool_rt, calc_tile_offset_original_zoom)
{
gnScreenWidth = 640;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight - 128;
zoomflag = false;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 8);
}
TEST(Scrool_rt, calc_tile_offset_960_540)
{
gnScreenWidth = 960;
gnScreenHeight = 540;
gnViewportHeight = gnScreenHeight;
zoomflag = true;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 2);
}
TEST(Scrool_rt, calc_tile_offset_853_480)
{
gnScreenWidth = 853;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight;
zoomflag = true;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 21);
EXPECT_EQ(y, 0);
}
TEST(Scrool_rt, calc_tile_offset_768_480_zoom)
{
gnScreenWidth = 768;
gnScreenHeight = 480;
gnViewportHeight = gnScreenHeight;
zoomflag = false;
int x = 0;
int y = 0;
CalcTileOffset(&x, &y);
EXPECT_EQ(x, 0);
EXPECT_EQ(y, 8);
}
// RowsCoveredByPanel
TEST(Scrool_rt, calc_tiles_covered_by_panel_original)
{
gnScreenWidth = 640;
zoomflag = true;
EXPECT_EQ(RowsCoveredByPanel(), 0);
}
TEST(Scrool_rt, calc_tiles_covered_by_panel_960)
{
gnScreenWidth = 960;
zoomflag = true;
EXPECT_EQ(RowsCoveredByPanel(), 4);
}
TEST(Scrool_rt, calc_tiles_covered_by_panel_960_zoom)
{
gnScreenWidth = 960;
zoomflag = false;
EXPECT_EQ(RowsCoveredByPanel(), 2);
}

148
test/stores_test.cpp

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

Loading…
Cancel
Save