Add integerSqrt and integerHypotenuse to Utils lib
authorWuzzy <Wuzzy2@mail.ru>
Fri, 19 Apr 2019 15:54:44 +0200
changeset 14832 d65e25e211d4
parent 14831 583d8b96fb30
child 14833 16d5951d4044
Add integerSqrt and integerHypotenuse to Utils lib
ChangeLog.txt
share/hedgewars/Data/Scripts/Multiplayer/Continental_supplies.lua
share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua
share/hedgewars/Data/Scripts/Multiplayer/WxW.lua
share/hedgewars/Data/Scripts/SimpleMission.lua
share/hedgewars/Data/Scripts/Utils.lua
--- a/ChangeLog.txt	Fri Apr 19 04:48:30 2019 +0200
+++ b/ChangeLog.txt	Fri Apr 19 15:54:44 2019 +0200
@@ -98,7 +98,7 @@
  + New call: SetTeamPassive(teamname, isPassive): Mark a team as passive. Passive teams do not play and are treated like frozen teams.
  + New return value: AddTeam/AddMissionTeam return <real team name>, <team index>
  + SetClanColor: Now accepts negative color argument for user clan color, like in AddTeam
- + Utils library: New calls: getReadableChallengeRecord, updateChallengeRecord
+ + Utils library: New calls: getReadableChallengeRecord, updateChallengeRecord, integerSqrt, integerHypotenuse
  + New callback: onGameResult(winningClan): Called when the game ends normally. winningClan = index of winning clan or -1 on draw
  + New callback: onCaseDrop(gear): Called at the point where a crate MIGHT be dropped between turns. Gear is the crate gear or nil
  + SendStat extension: Option to use predefined modes with siPointType, like "!POINTS" or "!TIME"
--- a/share/hedgewars/Data/Scripts/Multiplayer/Continental_supplies.lua	Fri Apr 19 04:48:30 2019 +0200
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Continental_supplies.lua	Fri Apr 19 15:54:44 2019 +0200
@@ -15,29 +15,6 @@
 HedgewarsScriptLoad("/Scripts/Utils.lua")
 HedgewarsScriptLoad("/Scripts/Tracker.lua")
 
---approximative version of square root. This function follows the babylonian method.
-function IntegerSqrt(num)
-	local temp=num
-	while(temp*temp-div(temp,2)>num)
-	do
-		temp=div((temp+div(num,temp)),2)
-	end
-
-	return math.abs(temp)
-end
-
--- sqrt(x^2,y^2), work without desyncs. is approximative
-function Norm(xx,yy)
-	--to fix overflows
-	if(((math.abs(xx)^2)+(math.abs(yy)^2))>2^26)
-	then
-		local bitr=2^13
-		return IntegerSqrt((div(math.abs(xx),bitr)^2)+(div(math.abs(yy),bitr)^2))*bitr
-	else
-		return IntegerSqrt((math.abs(xx)^2)+(math.abs(yy)^2))
-	end
-end
-
 -- returns 1 or -1 depending on where it is
 function GetIfNegative(num)
 	if(num<0)
@@ -67,9 +44,8 @@
 	SetVisualGearValues(healthtag, nil, nil, nil, nil, nil, nil, nil, nil, nil, GetClanColor(GetHogClan(hog)))
 end
 
---will use IntegerSqrt
 function FireGear(hedgehog,geartype,vx,vy,timer)
-	local hypo=Norm(vx,vy)
+	local hypo=integerHypotenuse(vx,vy)
 	return AddGear(div((GetGearRadius(hedgehog)*2*vx),hypo)+GetX(hedgehog), div((GetGearRadius(hedgehog)*2*vy),hypo)+GetY(hedgehog), geartype, 0, vx, vy, timer)
 end
 
@@ -861,7 +837,7 @@
 				SetState(CurrentHedgehog, gstMoving)
 			end
 			SetGearPosition(hog, GetX(hog),GetY(hog)-3)
-			hypo=Norm(math.abs(GetX(hog)-GetX(CS.TEMP_VALUE)),math.abs(GetY(hog)-GetY(CS.TEMP_VALUE)))
+			hypo=integerHypotenuse(math.abs(GetX(hog)-GetX(CS.TEMP_VALUE)),math.abs(GetY(hog)-GetY(CS.TEMP_VALUE)))
 			SetGearVelocity(hog, div((power_radius_outer-hypo)*power_sa*GetIfNegative(GetX(hog)-GetX(CS.TEMP_VALUE)),power_radius_outer), div((power_radius_outer-hypo)*power_sa*GetIfNegative(GetY(hog)-GetY(CS.TEMP_VALUE)),power_radius_outer))
 		end
 	end
--- a/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua	Fri Apr 19 04:48:30 2019 +0200
+++ b/share/hedgewars/Data/Scripts/Multiplayer/Space_Invasion.lua	Fri Apr 19 15:54:44 2019 +0200
@@ -1571,13 +1571,14 @@
 ------------------------------------------------------------
 ------------------------------------------------------------
 
-function DoHorribleThings(cUID)
+function HandleRadarBlip(cUID)
 
 	-- work out the distance to the target
 	local g1X, g1Y = GetGearPosition(CurrentHedgehog)
 	local g2X, g2Y = SI.vCircX[cUID], SI.vCircY[cUID]
 	local q = g1X - g2X
 	local w = g1Y - g2Y
+	-- Floating point operations are safe, it's only for visuals
 	local r = math.sqrt( (q*q) + (w*w) )	--alternate
 
 	local opp = w
@@ -2253,7 +2254,7 @@
 			SI.vCircY[i] = SI.vCircY[i] + SI.vCircDY[i]
 
 			if (CurrentHedgehog ~= nil) and (SI.rAlpha ~= 255) then
-				DoHorribleThings(i)
+				HandleRadarBlip(i)
 			end
 
 		end
--- a/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua	Fri Apr 19 04:48:30 2019 +0200
+++ b/share/hedgewars/Data/Scripts/Multiplayer/WxW.lua	Fri Apr 19 15:54:44 2019 +0200
@@ -724,6 +724,7 @@
 	g2X, g2Y = GetX(gear), GetY(gear)
 	q = g1X - g2X
 	w = g1Y - g2Y
+	-- Floating point operations are safe, it's only for visuals
 	r = math.sqrt( (q*q) + (w*w) )	--alternate
 
 	RCX = getGearValue(gear,"RX")
--- a/share/hedgewars/Data/Scripts/SimpleMission.lua	Fri Apr 19 04:48:30 2019 +0200
+++ b/share/hedgewars/Data/Scripts/SimpleMission.lua	Fri Apr 19 15:54:44 2019 +0200
@@ -27,6 +27,7 @@
 
 HedgewarsScriptLoad("/Scripts/Locale.lua")
 HedgewarsScriptLoad("/Scripts/Tracker.lua")
+HedgewarsScriptLoad("/Scripts/Utils.lua")
 
 --[[
 SimpleMission(params)
@@ -221,20 +222,6 @@
 	end
 end
 
--- Get hypotenuse of a triangle with legs x and y
-local function hypot(x, y)
-	local t
-	x = math.abs(x)
-	y = math.abs(y)
-	t = math.min(x, y)
-	x = math.max(x, y)
-	if x == 0 then
-		return 0
-	end
-	t = t / x
-	return x * math.sqrt(1 + t * t)
-end
-
 local errord = false
 
 -- This function generates the mission. See above for the meaning of params.
@@ -366,7 +353,7 @@
 				tX, tY = GetGearPosition(_G.sm.goalGears[goal.id2])
 			end
 
-			local h = hypot(gX - tX, gY - tY)
+			local h = integerHypotenuse(gX - tX, gY - tY)
 			if goal.relationship == "smallerThan" then
 				return h < goal.distance
 			elseif goal.relationship == "greaterThan" then
--- a/share/hedgewars/Data/Scripts/Utils.lua	Fri Apr 19 04:48:30 2019 +0200
+++ b/share/hedgewars/Data/Scripts/Utils.lua	Fri Apr 19 15:54:44 2019 +0200
@@ -104,6 +104,28 @@
 	drawFullMap(true, flush)
 end
 
+-- Approximative but desync-safe version of square root. This function follows the Babylonian method.
+function integerSqrt(num)
+	local temp = num
+	while (temp*temp - div(temp, 2) > num)
+	do
+		temp = div((temp + div(num, temp)), 2)
+	end
+	return math.abs(temp)
+end
+
+-- Integer square root of (x^2, y^2), works without desyncs. Is approximative.
+-- This is the same as the length of the hypotenuse of a triangle with legs x, y.
+function integerHypotenuse(x, y)
+	-- To fix overflows
+	if(((math.abs(x)^2) + (math.abs(y)^2)) > 2^26)
+	then
+		local bitr = 2^13
+		return integerSqrt((div(math.abs(x), bitr)^2) + (div(math.abs(y), bitr)^2)) * bitr
+	else
+		return integerSqrt((math.abs(x)^2) + (math.abs(y) ^ 2))
+	end
+end
 
 --[[ GLOBAL VARIABLES ]]