.tact9 LDA enemyDrainTimer,X \ If enemyDrainTimer for the enemy is zero then jump to BEQ tact11 \ tact11 to skip the following, as this timer is not in \ use LDY enemyTarget,X \ Set Y to the object number in enemyTarget, so when we \ refer to object #Y, it's the enemy's target object \ \ If this hasn't been set to a valid object number yet \ then the call to CheckEnemyGaze will simply say the \ object is not visible LDA #0 \ Call CheckEnemyGaze to check the gaze of the enemy JSR CheckEnemyGaze \ towards object #Y, returning the following if the \ the object is a robot (an object of type 0): \ \ * targetVisibility = bit 7 set if the object's tile \ is visible, bit 6 set if the object is visible LDA targetVisibility \ If the target is not a robot, or the target is a robot BEQ tact10 \ but the enemy can't see it, then jump to tact10 to \ keep applying tactics JMP tact19 \ Otherwise the target is a robot and the enemy can see \ at least some of it, so jump to part 7 with the target \ object number in Y to try draining energy from the \ robot .tact10 STA enemyDrainTimer,X \ Set enemyDrainTimer = 0 to restart the drain counter \ for the enemy in part 5 of ApplyTactics, so it doesn't \ drain energy for another 120 timer ticks (120 * 0.06 = \ 7.2 seconds) .tact11 \ We now loop through every object on the landscape, \ looking for a robot that the enemy can drain of energy \ (in other words, a robot whose tile the enemy can see) \ \ If the robot turns out to be the player object, then \ we also check whether the object LDA #%10000000 \ Set bit 7 of playerTileObscured, so by default the STA playerTileObscured \ the player object can't be seen at all (though we will \ change this in the following loop if the enemy can see \ the partially obscured player object) LDY #63 \ Set a counter in Y to work through the object numbers .tact12 LDA #0 \ Call CheckEnemyGaze to check the gaze of the enemy JSR CheckEnemyGaze \ towards object #Y, returning the following if the \ the object is a robot (an object of type 0): \ \ * targetVisibility = bit 7 set if the object's tile \ is visible, bit 6 set if the object is visible \ \ * treeVisibility = bit 7 set if there is a tree in \ the way of the robot's tile, bit 6 set if there is \ a tree in the way of the robot LDA treeVisibility \ If bit 6 of treeVisibility is set then there is a tree AND #%01000000 \ in the way between the enemy and the robot, so jump to BNE tact13 \ tact13 to move on to the next object LDA targetVisibility \ If targetVisibility is zero then both bits 6 and 7 are BEQ tact13 \ clear, so the enemy can't see the robot or the tile \ it's on, so jump to tact13 to move on to the next \ object BMI tact19 \ If bit 7 of targetVisibility is set then the enemy can \ see the robot's tile, so jump to part 7 with the \ robot's object number in Y to try draining energy from \ the robot CPY playerObject \ If the robot is not the player object then jump to BNE tact13 \ tact13 to move on to the next object STY playerTileObscured \ The robot is the player object and we know that bit 6 \ of targetVisibility must be set (as targetVisibility \ is non-zero and bit 7 is clear), so this means the \ enemy can see the player but it can't see the tile \ that the player is on \ \ So set playerTileObscured to the object number of the \ player, so we can process this fact after we have \ finished looping through the object (assuming the \ enemy doesn't first get distracted by a different \ robot whose tile it can see, which will take \ precedence) .tact13 DEY \ Decrement the counter in Y to move on to the next \ object number BPL tact12 \ Loop back to tact12 to check the next object number \ If we get here then we have checked all 64 object \ numbers and none of them are suitable robots for the \ enemy to drain, so now we check whether any of them \ are the partially obscured player object LDY playerTileObscured \ If bit 7 of playerTileObscured is set then we didn't BMI tact14 \ change it to the number of the player object in the \ above loop, so we didn't find a partially obscured \ player object so jump to tact14 to look for trees \ and boulders for the enemy to drain instead \ If we get here then the enemy can see the player \ but it can't see the tile that the player is on, and \ the player object number is in Y TYA \ If the value of enemyFailTarget for this enemy matches CMP enemyFailTarget,X \ the player object number, then this enemy already BEQ tact14 \ tried scanning for a tree to turn into a meanie to \ attack the player and they failed to find one, so jump \ to tact14 to look for trees and boulders for the enemy \ to drain instead JSR ResetMeanieScan \ Reset the data stored for any meanie scans that the \ enemy has tried in the past, so the enemy can start \ looking for potential meanies with a clean slate LDA #%01000000 \ Set targetVisibility to record that the enemy can see STA targetVisibility \ the player object (bit 6 set) but it can't see the \ tile the player is on (bit 7 clear), so we store this \ in the enemy's data when we jump to part 7 BNE tact19 \ Jump to part 7 with the target object number in Y to \ try draining energy from the target object (this BNE \ is effectively a JMP as A is never zero) .tact14 LDA #0 \ Set enemyDrainTimer = 0 to restart the drain counter STA enemyDrainTimer,X \ for the enemy in part 5 of ApplyTactics, so it doesn't \ drain energy for another 120 timer ticks (120 * 0.06 = \ 7.2 seconds) JSR FindObjectToDrain \ Find a suitable target object for the enemy to drain \ (i.e. a tree that is stacked on top of another object, \ or a boulder, which is exposed to the enemy and on a \ tile that can be seen by the enemy) \ \ If successful, the object number is in targetObject \ and the C flag is clear, otherwise the C flag is set BCS tact16 \ If FindObjectToDrain set the C flag, then no suitable \ object was found for the enemy to drain, so jump to \ tact16 to keep applying tactics .tact15 \ If we get here then we drain energy from the target \ object in targetObject JSR DrainObjectEnergy \ Drain energy from the target object into the enemy, \ transforming it into an object with an energy level \ of one unit less (if applicable) \ \ This updates enemyEnergy with the drained energy, so \ it can be expended back onto the landscape later on \ \ It also sets X to the object number of the target that \ has been drained of energy (and which has therefore \ been transformed into a different object type) BCS tact17 \ If DrainObjectEnergy set the C flag then the enemy \ just drained the player object, so jump to tact17 to \ move on to the next enemy in the next iteration of \ the gameplay loop, as we don't need to update the \ player object on-screen (as we never see the player \ object) LDY enemyObject \ Set enemyTacticTimer for the enemy to 30 so we wait LDA #30 \ for 30 * 0.06 = 1.8 seconds before applying tactics STA enemyTacticTimer,Y \ to the enemy again JMP tact25 \ Jump to tact25 with X set to the object number of \ the enemy to update it on-screen with a dithered \ effect (as it has now been transformed into a \ different type of object) and return from the \ subroutine using a tail call .tact16 LDX enemyObject \ Set X to the object number of the enemy to which we \ are applying tactics (so this is now object #X) LDA enemyRotateTimer,X \ If the rotation timer for the enemy is less than 2 CMP #2 \ then it has run all the way down, so jump to part 6 BCC tact18 \ to rotate the enemy .tact17 JMP MoveOnToNextEnemy \ Otherwise jump to MoveOnToNextEnemy to stop applying \ tactics to this enemy and set things up so we move on \ to the next enemy in the next iteration of the \ gameplay loopName: ApplyTactics (Part 5 of 8) [Show more] Type: Subroutine Category: Gameplay Summary: Look for a suitable robot to drain of energy, or look for a drainable tree or boulder if there are no suitable robotsContext: See this subroutine in context in the source code References: No direct references to this subroutine in this source file
[X]
Subroutine CheckEnemyGaze (Part 1 of 2) (category: Gameplay)
Check to see whether the current enemy can see a specific target object of a specific type
[X]
Subroutine DrainObjectEnergy (category: Gameplay)
Drain energy from an object into an enemy, transforming it into an object with an energy level of one unit less (if applicable)
[X]
Subroutine FindObjectToDrain (category: Gameplay)
Find a suitable target object for an enemy to drain
[X]
Subroutine MoveOnToNextEnemy (category: Gameplay)
Update enemyObject so the next time we consider applying enemy tactics, we apply them to the next enemy, looping from 7 to 0
[X]
Subroutine ResetMeanieScan (category: Gameplay)
Reset the data stored for any meanie scans that the enemy has tried in the past, so we can start looking with a clean slate
[X]
Variable enemyDrainTimer in workspace Main variable workspace
A timer for each enemy that counts down every 0.06
[X]
Variable enemyFailTarget in workspace Main variable workspace
Enemy failed to find meanie: target object (one byte
[X]
Variable enemyObject in workspace Zero page
The object number of the enemy to which we are applying tactics in this iteration around the main loop (0-7)
[X]
Variable enemyRotateTimer in workspace Main variable workspace
A timer for each enemy that counts down every 0.06
[X]
Variable enemyTacticTimer in workspace Main variable workspace
A timer for each enemy that counts down every 0.06
[X]
Variable enemyTarget in workspace Main variable workspace
The object number of the enemy's target (one byte per
[X]
Variable playerObject in workspace Zero page
The number of the player object
[X]
Variable playerTileObscured in workspace Zero page
Records when an enemy can see the player object but can't see the tile that the player is on
[X]
Label tact10 is local to this routine
[X]
Label tact11 is local to this routine
[X]
Label tact12 is local to this routine
[X]
Label tact13 is local to this routine
[X]
Label tact14 is local to this routine
[X]
Label tact16 is local to this routine
[X]
Label tact17 is local to this routine
[X]
Label tact18 in subroutine ApplyTactics (Part 6 of 8)
[X]
Label tact19 in subroutine ApplyTactics (Part 7 of 8)
[X]
Entry point tact25 in subroutine ApplyTactics (Part 8 of 8) (category: Gameplay)
Dither the updated object #X onto the screen, with bit 7 of drawLandscape determining whether the object is drawn on its own (bit 7 set) or with the surrounding landscape (bit 7 clear)
[X]
Variable targetVisibility in workspace Zero page
Reports whether a target object is visible from an enemy in the CheckEnemyGaze routine
[X]
Variable treeVisibility in workspace Main variable workspace
Reports whether a gaze is interrupted by a tree in the CheckEnemyGaze routine