I need help with making an if/then statement which depends on a movie clip being between a certain set of coordinates for the rule to work. Here is the code I tried to use:
if (honey1.x >=165 <=231.x;
honey1.y >=295 <=330.y;) {
honeyOne = true}
}
I haven't had much luck finding a lot of help on condition statements beyond very simple or unrelated notes. If anyone knows how to make a statement like this work, I would be most appreciative.
A method to test that a number is between two bounds might look like this.
bool IsBetweenInclusive(int value, int lower, int upper)
{
return value >= lower
&& value <= upper;
}
That's easily extendable to a point structure
bool IsBetweenInclusive(Point value, Point lower, Point upper)
{
return IsBetweenInclusive(value.X, lower.X, upper.X)
&& IsBetweenInclusive(value.Y, lower.Y, upper.Y);
}
If your coordinate system is in a double or float kind of number space, you'll need to do work to account for rounding.
Related
What I Am Doing: I am writing a chess engine in Swift. One of the most important parts of writing a strong chess engine is the ability to generate as many possible future board positions in as little time possible. The more positions your engine can generate and evaluate in a shorter amount of time, the stronger the engine is.
That being said, I've written functions for generating moves for sliding pieces (bishops, rooks, and queens). These functions make use of overflow operators (&+, &-, &*), as using normal bitwise operators frequently cause overflow errors.
Generating said moves requires two functions, one for generating all legal vertical and horizontal moves for a sliding piece, and one for generating all legal diagonal moves for a sliding piece. These two functions effectively go about doing the same thing, we just manipulate the arguments slightly differently. Here is what the function for generating horizontal and vertical moves looks like:
//occupied is a bitboard that represents every square on the chess board that is occupied
//this value is set somewhere before our move generation functions are ever called
var occupied: UInt64 = 0
//the rankMasks and fileMasks are simply arrays of bitboards that represent each individual file and rank on a chess board
//rankMasks8[0] would represent the squares a8-h8, rankMasks8[1] would represent the squares a7-h7
//fileMasks8[0] would represent the squares a1-a8, fileMasks8[1] would represent the squares b1-b8
let rankMasks8: [UInt64] = [ 255, 65280, 16711680, 4278190080, 1095216660480, 280375465082880, 71776119061217280, 18374686479671623680 ]
let fileMasks8: [UInt64] = [ 72340172838076673, 144680345676153346, 289360691352306692, 578721382704613384, 1157442765409226768, 2314885530818453536, 4629771061636907072, 9259542123273814144 ]
...
//We pass a square (0 - 63) as s and we are returned a UInt64, the bitboard representing all the squares that the piece on the passed square can move to.
func horizontalAndVerticalMoves(s: Int) -> UInt64 {
//convert the passed square into a bitboard that represents its location, by raising 2 to the power of s
let binaryS: UInt64 = 1<<s
//formula for generating possible horizontal moves
let possibilitiesHorizontal: UInt64 = (occupied &- (2 &* binaryS)) ^ UInt64.reverse(UInt64.reverse(occupied) &- 2 &* UInt64.reverse(binaryS))
//formula for generating vertical moves
let possibilitiesVertical: UInt64 = ((occupied & fileMasks8[s % 8]) &- (2 &* binaryS)) ^ UInt64.reverse(UInt64.reverse(occupied & fileMasks8[s % 8]) &- (2 &* UInt64.reverse(binaryS)))
//we return possible horizontal moves OR possible vertical moves
return (possibilitiesHorizontal & rankMasks8[s / 8]) | (possibilitiesVertical & fileMasks8[s % 8])
}
The only important thing you need to recognize about the above function is that it gives us the expected output and it does so using overflow operators.
Now, my previous iteration of this same method (before I understood how to circumvent the overflows using overflow operators) was much more drawn out. It required running four while loops that would move away from the current piece in either the "north", "south", "east", or "west" direction until it came into contact with a piece that blocks further movement in the respective direction. Here's what this iteration of the horizontalAndVerticalMoves function looked like:
func horizontalAndVerticalMoves(s: Int) -> UInt64 {
let rankMask: UInt64 = rankMasks8[s/8]
let fileMask: UInt64 = fileMasks8[s%8]
let pseudoPossibleMoves: UInt64 = rankMask ^ fileMask
var unblockedRanks: UInt64 = 0
var unblockedFiles: UInt64 = 0
var direction: Direction! = Direction.north
var testingSquare: Int = s - 8
while direction == .north {
if testingSquare < 0 || testingSquare%8 != s%8 {
direction = .east
} else {
if 1<<testingSquare&occupied != 0 {
unblockedRanks += rankMasks8[testingSquare/8]
direction = .east
} else {
unblockedRanks += rankMasks8[testingSquare/8]
testingSquare -= 8
}
}
}
testingSquare = s + 1
while direction == .east {
if testingSquare > 63 || testingSquare/8 != s/8 {
direction = .south
} else {
if 1<<testingSquare&occupied != 0 {
unblockedFiles += fileMasks8[testingSquare%8]
direction = .south
} else {
unblockedFiles += fileMasks8[testingSquare%8]
testingSquare += 1
}
}
}
testingSquare = s + 8
while direction == .south {
if testingSquare > 63 || testingSquare%8 != s%8 {
direction = .west
} else {
if 1<<testingSquare&occupied != 0 {
unblockedRanks += rankMasks8[testingSquare/8]
direction = .west
} else {
unblockedRanks += rankMasks8[testingSquare/8]
testingSquare += 8
}
}
}
testingSquare = s - 1
while direction == .west {
if testingSquare < 0 || testingSquare/8 != s/8 {
direction = .north
} else {
if 1<<testingSquare&occupied != 0 {
unblockedFiles += fileMasks8[testingSquare%8]
direction = .north
} else {
unblockedFiles += fileMasks8[testingSquare%8]
testingSquare -= 1
}
}
}
let mask = unblockedRanks | unblockedFiles
let possibleMoves = pseudoPossibleMoves&mask
return possibleMoves
}
I figured my newly implemented version of this function (the one that makes use of overflow operators) would be not only more succinct, but also much more efficient. The only important things you need to note about this iteration of the same function is that it gives us the expected output, but appears much more drawn out and doesn't use overflow operators.
What I've Noticed: As mentioned, I expected that my newer, cleaner code using overflow operators would perform much more quickly than the iteration that uses a bunch of while loops. When running tests to see how quickly I can generate chess moves, I've found that the version that uses while loops instead of overflow operators was significantly faster. Calculating every combination of the first three moves in a chess game takes the original function a little less than 6 seconds, while the newer function that uses overflow operators takes a little under 13 second.
What I'm Wondering: As I am wanting to create the strongest chess engine possible, I am hunting for bits of my code that I can make execute faster. The old function performing quicker than the new function seems counterintuitive to me. So I am wondering, are overflow operator in Swift notoriously slow/inefficient?
Here is what the class in question that generates these moves looks like: https://github.com/ChopinDavid/Maestro/blob/master/Maestro/Moves.swift
So I am wondering, are overflow operator in Swift notoriously slow/inefficient?
No, if anything the opposite might be true.
The machine-level instructions for multiply etc. may set an overflow flag but they don't do any more than that. For the standard operators Swift has to compile additional instructions to test that flag and generate an error and this code includes branches (though branch prediction should mitigate those effectively).
The code for your overflow operator version is shorter than that for the standard operator version, its also branch-free.
What the performance difference is between versions is another matter, but the overflow version should not be slower.
You probably need to look for your performance difference elsewhere. Happy hunting!
Note: the above comparison is based on fully optimised code ("Fastest, Smallest [-Os]") produced by the Swift compiler in Xcode 11.3.1, a debug build might produce very different results.
I have an if statement that is meant to check a float that increases over time (It's a timer) the current code is this
if (Day.DateTime == 1080){
ClientsTaken = Random.Range(MinNoOfClients, MaxNoOfClients);
GameObject.Find("Canvas").GetComponent(Brothel).Money += (ClientsTaken *(Cost * GirlMorale));
ClientsSeen += ClientsTaken;
Debug.Log("Clients taken = " + ClientsTaken);
}
The timer is definatly hitting 1080 but nothing is happening. I also tried 1080f but had the same result.
Any help would be greatly appreciated, thanks.
Comparing floating point variables this way is not recommended due to "floating point imprecision" - the way the floating point variables are internally stored on PC.
Instead, you can use Mathf.Approximately(), like this:
if (Mathf.Approximately(Day.DateTime, 1080.0))
{
...
{
I would change the check to Day.DateTime >= 1080. When dealing with floating point numbers you may not land directly on an integer value.
Which loop should I use when have to be extremely aware of the time it takes to iterate over a large array.
Short answer
Don’t micro-optimize like this – any difference there is could be far outweighed by the speed of the operation you are performing inside the loop. If you truly think this loop is a performance bottleneck, perhaps you would be better served by using something like the accelerate framework – but only if profiling shows you that effort is truly worth it.
And don’t fight the language. Use for…in unless what you want to achieve cannot be expressed with for…in. These cases are rare. The benefit of for…in is that it’s incredibly hard to get it wrong. That is much more important. Prioritize correctness over speed. Clarity is important. You might even want to skip a for loop entirely and use map or reduce.
Longer Answer
For arrays, if you try them without the fastest compiler optimization, they perform identically, because they essentially do the same thing.
Presumably your for ;; loop looks something like this:
var sum = 0
for var i = 0; i < a.count; ++i {
sum += a[i]
}
and your for…in loop something like this:
for x in a {
sum += x
}
Let’s rewrite the for…in to show what is really going on under the covers:
var g = a.generate()
while let x = g.next() {
sum += x
}
And then let’s rewrite that for what a.generate() returns, and something like what the let is doing:
var g = IndexingGenerator<[Int]>(a)
var wrapped_x = g.next()
while wrapped_x != nil {
let x = wrapped_x!
sum += x
wrapped_x = g.next()
}
Here is what the implementation for IndexingGenerator<[Int]> might look like:
struct IndexingGeneratorArrayOfInt {
private let _seq: [Int]
var _idx: Int = 0
init(_ seq: [Int]) {
_seq = seq
}
mutating func generate() -> Int? {
if _idx != _seq.endIndex {
return _seq[_idx++]
}
else {
return nil
}
}
}
Wow, that’s a lot of code, surely it performs way slower than the regular for ;; loop!
Nope. Because while that might be what it is logically doing, the compiler has a lot of latitude to optimize. For example, note that IndexingGeneratorArrayOfInt is a struct not a class. This means it has no overhead over declaring the two member variables directly. It also means the compiler might be able to inline the code in generate – there is no indirection going on here, no overloaded methods and vtables or objc_MsgSend. Just some simple pointer arithmetic and deferencing. If you strip away all the syntax for the structs and method calls, you’ll find that what the for…in code ends up being is almost exactly the same as what the for ;; loop is doing.
for…in helps avoid performance errors
If, on the other hand, for the code given at the beginning, you switch compiler optimization to the faster setting, for…in appears to blow for ;; away. In some non-scientific tests I ran using XCTestCase.measureBlock, summing a large array of random numbers, it was an order of magnitude faster.
Why? Because of the use of count:
for var i = 0; i < a.count; ++i {
// ^-- calling a.count every time...
sum += a[i]
}
Maybe the optimizer could have fixed this for you, but in this case it hasn’t. If you pull the invariant out, it goes back to being the same as for…in in terms of speed:
let count = a.count
for var i = 0; i < count; ++i {
sum += a[i]
}
“Oh, I would definitely do that every time, so it doesn’t matter”. To which I say, really? Are you sure? Bet you forget sometimes.
But you want the even better news? Doing the same summation with reduce was (in my, again not very scientific, tests) even faster than the for loops:
let sum = a.reduce(0,+)
But it is also so much more expressive and readable (IMO), and allows you to use let to declare your result. Given that this should be your primary goal anyway, the speed is an added bonus. But hopefully the performance will give you an incentive to do it regardless.
This is just for arrays, but what about other collections? Of course this depends on the implementation but there’s a good reason to believe it would be faster for other collections like dictionaries, custom user-defined collections.
My reason for this would be that the author of the collection can implement an optimized version of generate, because they know exactly how the collection is being used. Suppose subscript lookup involves some calculation (such as pointer arithmetic in the case of an array - you have to add multiple the index by the value size then add that to the base pointer). In the case of generate, you know what is being done is to sequentially walk the collection, and therefore you could optimize for this (for example, in the case of an array, hold a pointer to the next element which you increment each time next is called). Same goes for specialized member versions of reduce or map.
This might even be why reduce is performing so well on arrays – who knows (you could stick a breakpoint on the function passed in if you wanted to try and find out). But it’s just another justification for using the language construct you should probably be using regardless.
Famously stated: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil" Donald Knuth. It seems unlikely that you are in the %3.
Focus on the bigger problem at hand. After it is working, if it needs a performance boost, then worry about for loops. But I guarantee you, in the end, bigger structural inefficiencies or poor algorithm choice will be the performance problem, not a for loop.
Worrying about for loops is oh so 1960s.
FWIW, a rudimentary playground test shows map() is about 10 times faster than for enumeration:
class SomeClass1 {
let value: UInt32 = arc4random_uniform(100)
}
class SomeClass2 {
let value: UInt32
init(value: UInt32) {
self.value = value
}
}
var someClass1s = [SomeClass1]()
for _ in 0..<1000 {
someClass1s.append(SomeClass1())
}
var someClass2s = [SomeClass2]()
let startTimeInterval1 = CFAbsoluteTimeGetCurrent()
someClass1s.map { someClass2s.append(SomeClass2(value: $0.value)) }
println("Time1: \(CFAbsoluteTimeGetCurrent() - startTimeInterval1)") // "Time1: 0.489435970783234"
var someMoreClass2s = [SomeClass2]()
let startTimeInterval2 = CFAbsoluteTimeGetCurrent()
for item in someClass1s { someMoreClass2s.append(SomeClass2(value: item.value)) }
println("Time2: \(CFAbsoluteTimeGetCurrent() - startTimeInterval2)") // "Time2 : 4.81457495689392"
The for (with a counter) is just incrementing a counter. Very fast. The for-in uses an iterator (call object to pass the next element). This is much slower. But finally you want to access the element in both cases wich will then make no difference in the end.
I think I'm going insane.
"counter" and "interval" are both doubles. This is happening on accelerometer:didAccelerate at an interval of (.01) . "counter" should eventually increment to "interval". For some reason i cant get this "if" to ring true.
Am I overlooking something?
double interval = .5;
if( counter == interval ){ //should eventually be .50000 == .50000
NSLog( #"Hit!" );
[self playSound];
counter = 0;
}else{
counter += .01;
}
NSLog( #"%f, %f, %d",counter,interval,(counter == interval) );
Don't ever compare doubles or floats with equality - they might look the same at the number of significant figures your are examining but the computer sees more.
For this purpose, the Foundation Framework provides "epsilon" values for different types such as "float" and "double". If the distance between two numbers is smaller than epsilon, you can assume these two numbers are equal.
In your case, you would use it as follow:
- (BOOL)firstDouble:(double)first isEqualTo:(double)second {
if(fabs(first - second) < DBL_EPSILON)
return YES;
else
return NO;
}
Or in Swift 4:
func doublesAreEqual(first: Double, second: Double) -> Bool {
if fabs(first - second) < .ulpOfOne {
return true
}
return false
}
Two very useful links:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
Interesting discussion of Unit in Last Place (ULP) and usage in Swift
Friday Q&A 2011-01-04: Practical Floating Point
In your else block, you are not adding 0.01 to counter, because that is not a representable double-precision value. You are actually adding the value:
0.01000000000000000020816681711721685132943093776702880859375
Unsurprisingly, when you repeatedly add this value to itself, you never get 0.5 exactly.
Two options: the better is to replace the if condition with (counter >= interval). Alternatively, you could use a small power of two for the increment instead of something that cannot be represented, like 0.0078125.
So I have a very simple game going here..., right now the AI is nearly perfect and I want it to make mistakes every now and then. The only way the player can win is if I slow the computer down to a mind numbingly easy level.
My logic is having a switch case statement like this:
int number = randomNumber
case 1:
computer moves the complete opposite way its supposed to
case 2:
computer moves the correct way
How can I have it select case 2 68% (random percentage, just an example) of the time, but still allow for some chance to make the computer fail? Is a switch case the right way to go? This way the difficulty and speed can stay high but the player can still win when the computer makes a mistake.
I'm on the iPhone. If there's a better/different way, I'm open to it.
Generating Random Numbers in Objective-C
int randNumber = 1 + rand() % 100;
if( randNumber < 68 )
{
//68% path
}
else
{
//32% path
}
int randomNumber = GeneraRandomNumberBetweenZeroAndHundred()
if (randomNumber < 68) {
computer moves the complete opposite way its supposed to
} else {
computer moves the correct way
}
Many PRNGs will offer a random number in the range [0,1). You can use an if-statement instead:
n = randomFromZeroToOne()
if n <= 0.68:
PlaySmart()
else:
PlayStupid()
If you're going to generate an integer from 1 to N, instead of a float, beware of modulo bias in your results.