Jump to content
IGNORED

Logical operators in XB, vs mathematical operators in conditionals


OLD CS1

Recommended Posts

I have been looking at a COMPUTE! Magazine program from 1983 1984 called "Circus." Not sure why, but I felt compelled to OCR the PDF and then correct the text produced so it will actually run. I noticed a few inefficiencies, but what particularly caught my eye were lines like these:

380 IF ((H=104)+(H=112)+(H=120)+(H=128))*(FL=1)THEN GOSUB 50:: GOTO 290
390 IF (H=104)+(H=112)+(H=120)+(H=128)THEN GOSUB 50 :: DY=1 :: GOTO 290

Instead of using Extended BASIC's logical OR and AND operators, the programmer used the + and * mathematics as if programming in regular TI BASIC.

 

Are there any performance benefits to using one over the other in Extended BASIC?

 

The full listing follows.

 

 

10 DIM D1(20),E(20):: RANDOMIZE :: GOTO 110
20 REM BOING!
30 FOR VOL=1 TO 30 STEP 6 :: CALL SOUND(-50,VOL+110,VOL):: NEXT VOL:: RETURN
40 REM SCORE
50 CALL HCHAR(ROW+DY,COL+DX,32):: CALL SOUND(10,-5,1):: SC=SC+(H=120)*-50+(H=112)*-75+(H=104)*-100+((H=128)*(M1=1)*250):: BAL=BAL+1
60 IF BAL=84 THEN 150
70 IF (M1=0)*(H=128)THEN GOSUB 820 ELSE DISPLAY AT (1,10):STR$(SC);
80 M1=INT(RND*2):: IF M1=1 THEN CALL COLOR(13,11,1)ELSE CALL COLOR(13,2,1)
90 IF (SC>(2000*VAR))THEN LIFE=LIFE+2 :: VAR=VAR+1 :: G1=1 :: GOSUB 820 :: G1=0
100 RETURN
110 GOSUB 430
120 G$=" abc "
130 VAR=1 :: SC=0
140 LIFE=3 :: V(0)=-1 :: V(1)=0 :: V(2)=1
150 Y=23 :: X=13 :: COL=16 :: BAL=0:: CALL CLEAR :: CALL SCREEN(15)
160 M1=INT(RND*2):: IF M1=1 THEN CALL COLOR(13,11,1) ELSE CALL COLOR(13,2,10)
170 CALL HCHAR(2,2,100,30):: CALL HCHAR(24,2,102,30):: CALL VCHAR(3,2,101,21):: CALL VCHAR(3,31,101,21)
180 CALL HCHAR(3,3,104,28):: CALL HCHAR(4,3,112,28):: CALL HCHAR(5,3,120,13):: CALL HCHAR(5,19,120,12)
190 DISPLAY AT(1,3):"SCORE:";SC;TAB(18);"LIVES: ";LIFE
200 CALL HCHAR(17,3,103,7):: CALL HCHAR(17,24,103,7)
210 DISPLAY AT(Y,X):G$
220 CALL MAGNIFY(3):: FOR T=1 TO 3:: CALL SPRITE(#T,136,2+RND*12,RND*90+50,120,0,RND*20+10):: NEXT T
230 F=RND*27+3 :: CALL HCHAR(3,F,128)
240 FOR I=19 TO 5 STEP -1 :: CALL HCHAR(I+2,COL,32,3):: CALL HCHAR(I+1,COL,32,3) :: CALL HCHAR(I,COL,120,3):: CALL HCHAR(I+1,17,96):: NEXT I
250 DISPLAY AT(8,4):"PRESS ANY KEY TO START"
260 CALL KEY(0,K,S):: IF S=0 THEN 260
270 FOR GS=4 TO 27 :: CALL HCHAR(8,GS,32):: FOR J1=1 TO 10 ::NEXT J1 :: NEXT GS
280 ROW=6 :: COL=COL+1 :: DY=1 :: DX=0
290 CALL KEY(0,K,S):: IF (K<>44)*(K<>46)THEN 320
300 X=X+(K=44)+SGN(24-X)*(K=46)*-1
310 DISPLAY AT (23,X):G$
320 CALL GCHAR(ROW+DY,COL+DX,H):: IF H=32 THEN 400
330 IF H=101 THEN CALL HCHAR(ROW,COL,32):: DX=-DX :: GOTO 290
340 IF (H=103)*(DY=-1)THEN CALL HCHAR(ROW,COL,32):: ROW=ROW-2 :: CALL GCHAR(ROW,COL+2*DX,H):: COL=COL+2*DX+SGN(DX)*(H=101) :: GOTO 320
350 IF (H=100)+((H=103)*(DY=1))THEN DY=-DY :: DX=V(INT(RND*3)):: GOSUB 30 :: GOTO 320
360 IF (H>96)*(H<100)THEN DX=V(H-97) :: DY=- DY :: GOSUB 30 :: GOTO 400
370 IF (H=102)THEN GOSUB 820
380 IF ((H=104)+(H=112)+(H=120)+(H=128))*(FL=1)THEN GOSUB 50:: GOTO 290
390 IF (H=104)+(H=112)+(H=120)+(H=128)THEN GOSUB 50 :: DY=1 :: GOTO 290
400 CALL HCHAR(ROW,COL,32):: ROW=ROW+DY :: COL=COL+DX
410 CALL HCHAR(ROW,COL,96)
420 GOTO 290
430 FOR I=0 TO 3 :: CALL CHAR(104+I*8,"1C3E2F3F3F7E6000"):: NEXT I
440 CALL COLOR(10,7,1):: CALL COLOR(11,13,1):: CALL COLOR(12,5,1)
450 FOR I=96 TO 99 :: READ A$ :: CALL CHAR(I,A$):: NEXT I
460 DATA 3A3A127C10384444,FF30304848848484,FF00000000000000
470 DATA FF0C0C1212212121
480 CALL CHAR(136,"1C0F0703C1EF7F7F3F0F03070F1E38000000C0DEFAFEFFFCF0E0C0C080000000")
490 FOR I=100 TO 103 :: CALL CHAR(I,"AA55AA55AA55AA55") :: NEXT I
500 FOR T=1 TO 20 :: READ D1(T),E(T) :: NEXT T
510 DATA 200,523,200,494,100,466,100,494,100,466,100,440,200,415,200,392,200,370,200,392
520 DATA 200,440,200,392,100,370,100,392,100,370,100,349,200,330,200,311,200,294,200,311
530 F=1 :: F1=7 :: F2=13 :: F3=5 :: T=14
540 CALL CLEAR :: CALL SCREEN(15)
550 DISPLAY AT (8,10):"hpxhpxhpxh" :: DISPLAY AT(9,10):"p        x " :: DISPLAY AT (10,10):"h CIRCUS p"
560 DISPLAY AT (11,10): "x        h" :: DISPLAY AT(12,10):"hpxhpxhpxh"
570 FOR R=1 TO 20 :: CALL COLOR(10,F1,F,11,F2,F,12,F3,F)
580 T=F1 :: F1=F2 :: F2=F3 :: F3=T :: CALL SOUND(D1(R),E(R),2):: NEXT R
590 DISPLAY AT (22,3):"INSTRUCTIONS (Y/N)?" :: ACCEPT AT(22,23)VALIDATE("YN"):A$
600 IF A$="N" THEN RETURN
610 CALL CLEAR :: PRINT "THIS IS THE GAME OF CIRCUS."
620 PRINT :: PRINT "THE OBJECT OF THE GAME IS"
630 PRINT :: PRINT "TO POP ALL OF THE BALLOONS"
640 PRINT :: PRINT "WITH THE MAN. TO CATCH THE"
650 PRINT :: PRINT "MAN, POSITION THE TRAMPOLINE"
660 PRINT :: PRINT "WITH THE '<' AND '>' KEYS."
670 PRINT :: PRINT "ALL BORDERS, BUT THE BOTTOM,"
680 PRINT :: PRINT "WILL BOUNCE THE MAN BACK."
690 PRINT :: PRINT :: PRINT "AN EXTRA MAN WILL BE AWARDED"
700 PRINT :: PRINT "FOR EVERY 2000 POINTS." :: PRINT :: PRINT :: PRINT "PRESS ANY KEY TO CONTINUE"
710 CALL KEY(0,K,S):: IF S=0 THEN 710
720 CALL CLEAR
730 PRINT :: PRINT "BE CAREFUL OF THE BALLOON ON"
740 PRINT :: PRINT "THE TOP ROW WHICH CHANGES"
750 PRINT :: PRINT "COLOR. WHEN THIS BALLOON IS" :: PRINT :: PRINT "BLACK, IT WILL BLOW UP IN"
760 PRINT :: PRINT "YOUR MAN'S FACE IF IT IS"
770 PRINT :: PRINT "YELLOW, YOU WILL RECEIVE 250"
780 PRINT :: PRINT "POINTS." :: PRINT :: PRINT :: PRINT :: PRINT TAB(10);"GOOD LUCK!"
790 PRINT:: PRINT:: PRINT :: PRINT TAB(4);"PRESS ANY KEY TO START"
800 CALL KEY (0,K,S):: IF S=0 THEN 800 ELSE RETURN
810 REM LIFE-1
820 LIFE=LIFE-1 :: DISPLAY AT(1,25):STR$(LIFE):: IF LIFE=0 THEN 870
830 IF G1=0 THEN DISPLAY AT(Y,X):"   " :: CALL HCHAR(ROW,COL,32):: ROW=6 :: COL=17 :: DX=0 :: X= 13 :: CALL HCHAR(ROW,COL,96):: DISPLAY AT(Y,X):G$
840 IF G1=1 THEN RETURN
850 CALL KEY(0,K,S):: IF S=0 THEN 850
860 RETURN
870 DISPLAY AT(8,7):"G A M E   O V E R" :: DISPLAY AT(11,7):"PLAY AGAIN (Y/N)?"
880 ACCEPT AT(11,25)BEEP VALIDATE("YN"):H$ :: IF H$="Y" THEN 130 ELSE CALL DELSPRITE(ALL):: CALL CLEAR :: STOP

 

 

  • Like 1
Link to comment
Share on other sites

Nice, I typed in Circus way back when! BTW It was February 1984 issue of Compute! magazine.

 

My experience with writing Aperture in pure BASIC definitely exposed that the more complex your logic statement, the longer it takes for the interpreter to process it. So you're better off in most cases to check your most common scenario (which would be in this case, a space) so you can immediately act on it.

 

As to what is better, using AND/OR or the mathematical statements, I'm sure some of our XB guys who have mined the cartridge and spun their own versions can tell us for sure. :) I would surmise though that those lines would be equally over-complex even using AND and OR, as every condition has to be considered.

 

On a whole, the game could have been written to be much more efficient. It has the look that the original conversion was started in BASIC and then switched to Extended BASIC for performance improvements. But they still are using character graphics for movement, when using a sprite would be MUCH more efficient. (The pigeons are just a complete waste.) In fact, you could probably implement the Atari/Commodore 64 game design of two clowns on a see-saw in Extended BASIC. Hmm... maybe I'll do that. :)

Edited by adamantyr
Link to comment
Share on other sites

 

 

What AND OR operators are there in XB?

In TI BASIC, in order to do AND and OR operations, you have to utilize math.

 

Some examples:

 

IF A AND B THEN = IF (A<>0)*(B<>0) THEN

IF A OR B THEN = IF (A<>0)+(B<>0) THEN

 

The principal is that any value check inside parenthesis will equate to either 0 (if false) or -1 (if true). Don't ask my why it's not 1, some weirdness in the interpreter...

 

In TI Extended BASIC, you have AND and OR keywords available so you can use those instead. Doing a variable alone is equivalent to "Is this variable not zero?"

 

You can also do bitwise operations in Extended BASIC, which is awesome. If you do a statement like "IF A AND 32 THEN" it will actually do a bitwise check of A using the provided value as a bitmask.

 

So if A was equal to 36: 00100100

And you did A AND 32: 00100000

 

Then the result is 32, not zero, and the IF statement passes!

Edited by adamantyr
Link to comment
Share on other sites

In TI BASIC, in order to do AND and OR operations, you have to utilize math.

 

Some examples:

 

If A AND B THEN

Why isn't this in the manual? I mean, I've searched the manual (linked) for XOR and and and OR and that stuff but I didn't find them. I did find an example of an "AND" operation but it consisted of an if then else syntax that really confused me. Or am I losing it real fast?

 

Page 96

 

IF A = 1 THEN IF B = 2 THEN C = 3 ELSE
D = 4 ELSE E = 5 operates as follows: If
A is not equal to 1, then E is set equal to
5 and control passes to the next line, If A
is equal to 1 and B is not equal to 2, then
D is set equal to 4 and control passes to
the next line. If A is equal to 1 and B is
equal to 2, then C is set equal to 3 and
control passes to the next line.
>100 IF A=1 THEN IF B=2 THEN C=3
Now I went ahead and tried it with this..

 

10 a=1::b=1

20 if a=1 and b=1 then c=1
30 print c
my result was 0 but I also didn't get a syntax error. EDIT _ OOOOPS - I typed
20 if a=1 and b=1 then c=1
20 print c

 

Why isn't this in the manual? Or where exactly in the manual is AND OR mentioned as operators?

EDIT: OK Logically that weird if-then-else statement makes sense to me after reading it a few times. I get that now. But AND OR as typed operations would be great.

 

 

This changes everything.

Edited by Sinphaltimus
Link to comment
Share on other sites

 

We say that all the time about the Editor Assembler manual as well. :D

I was going to apologize for being a dumbass until I saw your response. LOL. Yeah. I dunno. How disappointed I was without the use of AND OR and now NOT, I was stuck with <,>,<>,= this whole time. Because things I tried like | & didn't work. *scratches head* thanks for the chuckle.

Edited by Sinphaltimus
Link to comment
Share on other sites

The principal is that any value check inside parenthesis will equate to either 0 (if false) or -1 (if true). Don't ask my why it's not 1, some weirdness in the interpreter...

Not at all. Zero is zero, regardless of the system. If we look at 16 bits only, then not(0000H) = FFFFH. But in two complement notation, FFFFH = -1. Thus inverting all bits in zero returns minus one. This is true regardless of the number of bits, as long as we look at integers. It would not be true in the radix 100 floating point format used in the 99/4A, though.

Link to comment
Share on other sites

You have to be careful how you use the logical operators because they are bitwise operators operating on 16-bit values (-32768 – 32767). This is why TRUE = -1 (all bits set) and FALSE = 0 (all bits cleared). Running the following code may surprise you with the third result:

 

X = 1

PRINT X=0; NOT(X=0); NOT X

0 -1 -2

 

The first expression X=0 = 0 (FALSE) because X = 1. The second expression NOT(X=0) = NOT 0 = -1 (TRUE). You may have been surprised with the third result: NOT X = NOT 1 (binary: 0000000000000001) = -2 (binary: 1111111111111110). This could ruin your day if you expected FALSE in an IF statement because any value except 0 is treated as being true.

 

Here is another example:

 

X = 20

Y = 10

PRINT X AND Y

0

 

The binary representation shows why this is correct:

 

0000000000010100 AND

0000000000001010

----------------

0000000000000000

 

...lee

Link to comment
Share on other sites

Not at all. Zero is zero, regardless of the system. If we look at 16 bits only, then not(0000H) = FFFFH. But in two complement notation, FFFFH = -1. Thus inverting all bits in zero returns minus one. This is true regardless of the number of bits, as long as we look at integers. It would not be true in the radix 100 floating point format used in the 99/4A, though.

 

I think your last sentence may be misleading, Anders. Though the representation of numbers in XB is, in fact, radix 100, before using the logical operators, XB rounds the number to an integer. If any of the numbers are greater than 32767 or less than -32768, XB will issue an error. Consider the following:

 

X = 122.55678

Y = 123

PRINT 0 OR X; X=Y; X AND Y

123 0 123

Z = 123E10

PRINT Z

1.23E+12

PRINT Z OR 0

* BAD VALUE

...lee

Edited by Lee Stewart
Link to comment
Share on other sites

The relationship operators are pretty handy, particularly for single expressions that require a true/false answer that may aid in computing another value.

 

For example, adding a preceding zero to a printed list of numbers:

FOR K=1 to 15

PRINT RPT$("0",-(K<10))&STR$(K)

NEXT K

 

Perhaps you want to toggle a value between two numbers:

1 Z=40

2 Z=-(80*(Z=40)+40*(Z=80))

3 PRINT Z::GOTO 2

 

As Lee points out, the logical (AND, OR, etc) operators can be tricky because depending on the expression, they can be used to generate either a true/false or a bitwise result.

  • Like 2
Link to comment
Share on other sites

Substituting AND/OR for */+ in line 380 and looping that comparison one thousand times yielded less than 1 second variation between operator usage. (35 seconds versus 36).

 

It isn't clear to me how the interpreter handles these internally, i.e., does it convert one to the other and use the same comparison code? Perhaps RXB or some other folks know those details. I have always used the mathematical relationship operators because long ago I was told they were faster and I like to avoid the bitwise gotchas. I never tried to prove that first claim...

Link to comment
Share on other sites

Yeah, I think internally it all uses the same system.

 

That said, you could improve performance. My favorite? Use POS. Put your potential characters into a string and then use POS to check what you find, and an ON GOTO after to route to specific routines.

 

I had forgotten about that, but I used it a LOT in my own programs. Between converting the numbers to FP to make comparisons and looking up the string to make comparisons, I bet the difference there is minimal, as well.

Link to comment
Share on other sites

Perhaps you want to toggle a value between two numbers:

1 Z=40

2 Z=-(80*(Z=40)+40*(Z=80))

3 PRINT Z::GOTO 2

or

 

1 Z=40

2 Z=120-Z

3 PRINT Z::GOTO 2

 

Your strategy can be used for "toggling" between any number of numbers though. Maybe an array would quickly end up being nicer.

 

;)

Edited by sometimes99er
  • Like 1
Link to comment
Share on other sites

Yes, I kept it a bit short, so I didn't go into the implict conversion between real and integer when the logical operators are used. Floating point multiply is for sure more complex than AND, but using AND suffers from the conversion real -> integer before and integer -> real after the operation. This is more efficient in for example Pascal, where you can use integers as variables. Hence the conversions aren't needed.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...