blainelocklair Posted December 3, 2018 Share Posted December 3, 2018 Hi everyone! In the game2.bas game, I can see that the walls for the rooms are predesigned with this code: for y=0 to 11 read #line for x=0 to 15 if #line and $8000 then print at y*20+x+2,"\95" #line = #line * 2 next room0: DATA $FFFF,$8001,$8001,$87E1,$8021,$8020 DATA $8020,$8021,$87E1,$8001,$8001,$FFFF room1: DATA $FFFF,$8001,$8001,$8421,$8421,$8421 DATA $8421,$8421,$8421,$8001,$8001,$FC3F So, my questions are: 1) Where did the $ codes come from in the DATA lines? 2) I see there are six in each DATA line. Are six needed each time, kind of like color stacks on backgrounds need four (if I'm right about that)? 3) I can see that the room border is drawn by the for/next code. Does the $8000 refer to the "exit" on the border of the rooms? I can't see the $8000 in the DATA code, so I assume it must refer to the absence of DATA somehow. I do see that the "/95" must refer to the GROM ASCII code, which is a blank box. 4) Can the generation of the room's internal walls be randomized somehow? Even if the blocks are not connected, and just some finite number of them are randomly present, can that be done with a loop or something similar? I would like to expand on building new mazes, which is the reason for all the questions. I'm good with hard coding a bunch of mazes, and maybe even just calling on them randomly instead. I really just have to start with understanding how the walls are built with the DATA $ code and how they form the straightness or bends in the walls. Thanks! Blaine 1 Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 3, 2018 Share Posted December 3, 2018 The answer to where they came from is easy: magic numbers! Sorry, I couldn't resist because some people here just seem to love sharing examples with obscure numbers without context. Now for an actually answer that I hope helps. I believe those are BACKTAB words. The BACKTAB word format depends on the color mode (Color Stack or FG/BG). It is a 16-bit bitfield where specific groups of bits serve to define attributes, such as the card to use and its color. Take a look at the "STIC.TXT" file in the documents folder of the SDK for the definition of these words for Color Stack and for FG/BG mode. The $8000 represents bit 15 on a 16-bit word. The expression "#line and $8000" tests to see if bit 15 is set by masking[/] that bit and isolating it from the rest of the word . If so, it prints a particular sequence of characters. I haven't analyzed the code to see precisely what it's doing, so someone else may have to chime in for that. dZ Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 3, 2018 Author Share Posted December 3, 2018 Hi dZ! I kind of get it, but kind of dont. I get that the STIC has the 20x12 cards, eight pixels each, totaling 159x96 because #160 isn't shown. I also see that the STIC sees the $ formulas to identify where a card is on the screen. Cool. Here's what I don't get: the STIC formulas on the Intellivision Wiki don't start with eights. They start at $0200 and have $0200 numbers and letters associated with the cards. That's what throws me about the game2.bas DATA code lines. If I understand correctly, these types of lines couldn't be drawn with sprites because the Inty can't show enough of them to make that large of lines. That would make sense to me as to why the STIC just has what I believe to be ASCII from the GROM showing. Then it just deals with five sprites. I just don't get where the DATA code comes from since it doesn't match the STIC code on the wiki. It will all come together for me soon. I'm persistent. Thanks!Blaine Quote Link to comment Share on other sites More sharing options...
carlsson Posted December 3, 2018 Share Posted December 3, 2018 (edited) The AND is bitwise. If we convert the hexadecimal numbers to bit patterns, it might make more sense: $FFFF = "oooooooooooooooo" $8001 = "o..............o" $8001 = "o..............o" $87E1 = "o....oooooo....o" $8021 = "o.........o....o" $8020 = "o.........o....." $8020 = "o.........o....." $8021 = "o.........o....o" $87E1 = "o....oooooo....o" $8001 = "o..............o" $8001 = "o..............o" $FFFF = "oooooooooooooooo" So the loop reads 12 values, one for each row. Then it checks if the highest bit $8000 is set, and in that case plots a wall in that place. The calculation #line = #line * 2 is a poor man's arithmetic shift left, meaning that the highest bit will fall outside of what a 16-bit variable can hold, and the rest will be shifted one bit to the left. The loop tests all 16 bits if the (current) highest bit is set and plots a wall. As you can see, the PRINT AT has a +2 modifier in order to center the screen instead of leaving 4 columns to the right unused. Since a 16-bit variable can't hold 20 bits of information (though two 10-bit DECLES might), not all of the screen is used here. If you are unfamiliar with bit operations like shifting, AND, OR, XOR etc to retrieve, set or invert selected bits, it is worth learning. While most of everyday programming can be solved without those operations, sometimes you can obtain very elegant solutions using them. I don't know if bitwise OR is foreign to the CPU just like logical OR is, but at least the AND operator seems native. By the way, here is another way of writing the same code: for x=0 to 15 if #line and 1 then print at y*20+15-x+2,"\95" #line = #line / 2 next Edited December 3, 2018 by carlsson 2 Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 3, 2018 Author Share Posted December 3, 2018 Carlsson to the rescue! This, plus the attached graphic, finally brings together the concepts for me. I made a special game2.bas maze with a special message built into it. The map you laid out in your post above helped me understand that the DATA statements with the $ represent binary and are written in hex codes. Each of the hex codes adds four binary bits to the 12x16 grid. Once I saw the bits as hex codes, I was able to create them customized for my own. So very cool. Again, I can't tell you how grateful I am for your help and everyone's help here on the forums. I would never be able to learn this stuff without your guiding hands. The maze message is for all of you for your help! There are 10 kinds of people in this world: those that understand binary and those that don't. Blaine 4 Quote Link to comment Share on other sites More sharing options...
nanochess Posted December 4, 2018 Share Posted December 4, 2018 I'm glad you could solve it and Carlsson explained it very nicely. I think I wrote that game before IntyBASIC supported binary numbers, but now it supports the ampersand operator for binary numbers. So effectively the room 0 can be rewritten as: room0: DATA &1111111111111111 ' $ffff DATA &1000000000000001 ' $8001 DATA &1000000000000001 ' $8001 DATA &1000011111100001 ' $87E1 DATA &1000000000100001 ' $8021 DATA &1000000000100000 ' $8020 DATA &1000000000100000 ' $8020 DATA &1000000000100001 ' $8021 DATA &1000011111100001 ' $87E1 DATA &1000000000000001 ' $8001 DATA &1000000000000001 ' $8001 DATA &1111111111111111 ' $ffff And in fact with this arrangement you don't need to understand binary Please note the apostrophe character marks everything at its right as a comment. 2 Quote Link to comment Share on other sites More sharing options...
nanochess Posted December 4, 2018 Share Posted December 4, 2018 I've modernized the code, didn't had alterations almost since IntyBASIC creation. It will be included in the next IntyBASIC update. REM REM Barzack REM Demo for IntyBASIC REM by Oscar Toledo G. http://nanochess.org REM Jan/28/2014. REM REM Include useful predefined constants INCLUDE "constants.bas" WAIT DEFINE DEF00,4,drawings restart: WAIT room=0 #score=0 load_room: IF room = 0 THEN RESTORE room0 : #monster = SPR03 + SPR_GREEN IF room = 1 THEN RESTORE room1 : #monster = SPR00 + SPR_GREEN ' Deactivate sprites SPRITE 0,0,0 SPRITE 1,0,0 SPRITE 2,0,0 SPRITE 3,0,0 SPRITE 4,0,0 WAIT ' Wait to reset collision bits ' ' Clean screen ' CLS ' ' Draw current score in vertical ' PRINT AT (SCREENPOS(0, 0)),(#score/100%10+16)*8+6 PRINT AT (SCREENPOS(0, 1)),(#score/10%10+16)*8+6 PRINT AT (SCREENPOS(0, 2)),(#score%10+16)*8+6 PRINT COLOR CS_BLUE ' ' Draw room line per line ' Extract bit per bit of value to signal labyrinth value ' FOR y = 0 TO 11 READ #line FOR x = 0 TO 15 IF #line AND $8000 THEN PRINT AT y*20+x+2,"\95" #line = #line * 2 NEXT x NEXT y ' ' Setup some random barzacks ' y = 1: GOSUB barzack: y2 = y * 8 + 8: x2 = result y = 4: GOSUB barzack: y3 = y * 8 + 8: x3 = result y = 7: GOSUB barzack: y4 = y * 8 + 8: x4 = result y = 10: GOSUB barzack: y5 = y * 8 + 8: x5 = result ' ' Player start ' x1 = 32 y1 = 28 room = room + 1 IF room = 2 THEN room = 0 loop: WAIT ' ' Update MOBs ' SPRITE 0,X1+HIT+VISIBLE,Y1+ZOOMY2,SPR02 + SPR_RED ' Our hero SPRITE 1,X2+HIT+VISIBLE,Y2+ZOOMY2,#monster ' Mutant barzack SPRITE 2,X3+HIT+VISIBLE,Y3+ZOOMY2,#monster ' Mutant barzack SPRITE 3,X4+HIT+VISIBLE,Y4+ZOOMY2,#monster ' Mutant barzack SPRITE 4,X5+HIT+VISIBLE,Y5+ZOOMY2,#monster ' Mutant barzack ' ' Check for collision ' IF COL0 AND (HIT_SPRITE1+HIT_SPRITE2+HIT_SPRITE3+HIT_SPRITE4+HIT_SPRITE5+HIT_BACKGROUND) THEN GOTO touched IF COL1 AND HIT_BACKGROUND THEN Y2=0:BLINK=1 IF COL2 AND HIT_BACKGROUND THEN Y3=0:BLINK=1 IF COL3 AND HIT_BACKGROUND THEN Y4=0:BLINK=1 IF COL4 AND HIT_BACKGROUND THEN Y5=0:BLINK=1 ' Check for movement IF CONT1.UP THEN IF Y1>0 THEN Y1=Y1-1 IF CONT1.DOWN THEN IF Y1<104 THEN Y1=Y1+1 IF CONT1.LEFT THEN IF X1>0 THEN X1=X1-1 IF CONT1.RIGHT THEN IF X1<168 THEN X1=X1+1 ' Check for change of room IF Y1<8 OR X1<24 OR X1>144 OR Y1>96 THEN #score=#score+1:GOTO load_room ' Background sound SOUND 0,2000,FRAME AND 15 IF BLINK THEN SOUND 1,500,15:BLINK=0 ELSE SOUND 1,,0 ' Barzacks displacement IF FRAME AND 7 THEN GOTO loop IF Y2=0 THEN GOTO avoid1 IF X1<>X2 THEN IF X1<X2 THEN X2=X2-1 ELSE X2=X2+1 IF Y1<>Y2 THEN IF Y1<Y2 THEN Y2=Y2-1 ELSE Y2=Y2+1 avoid1: IF Y3=0 THEN GOTO avoid2 IF X1<>X3 THEN IF X1<X3 THEN X3=X3-1 ELSE X3=X3+1 IF Y1<>Y3 THEN IF Y1<Y3 THEN Y3=Y3-1 ELSE Y3=Y3+1 avoid2: IF Y4=0 THEN GOTO avoid3 IF X1<>X4 THEN IF X1<X4 THEN X4=X4-1 ELSE X4=X4+1 IF Y1<>Y4 THEN IF Y1<Y4 THEN Y4=Y4-1 ELSE Y4=Y4+1 avoid3: IF Y5=0 THEN GOTO avoid4 IF X1<>X5 THEN IF X1<X5 THEN X5=X5-1 ELSE X5=X5+1 IF Y1<>Y5 THEN IF Y1<Y5 THEN Y5=Y5-1 ELSE Y5=Y5+1 avoid4: GOTO loop touched: FOR color = 0 TO 31 WAIT SPRITE 0,X1+HIT+VISIBLE,Y1+ZOOMY2,SPR02+(color AND SPR_WHITE) ' Our hero SOUND 0,(color and 7)*32+32,15 SOUND 1,(color and 7)*36+32,15 SOUND 2,(color and 7)*40+32,15 NEXT color SOUND 0,,0 SOUND 1,,0 SOUND 2,,0 FOR loop = 0 to 100 WAIT NEXT loop ' Deactivate sprites SPRITE 0,0,0 SPRITE 1,0,0 SPRITE 2,0,0 SPRITE 3,0,0 SPRITE 4,0,0 GOTO restart ' ' Locate a free space for a barzack ' Input: y = Screen row ' barzack: PROCEDURE DO WAIT X = RAND % 16 LOOP WHILE #BACKTAB(Y * BACKGROUND_COLUMNS + X + 2) result = (x + 2) * 8 + 8 END ' ' Definition of rooms ' ' Uses binary numbers to form a 16-bit value ' (the maximum fitting a DATA value) ' room0: DATA &1111111111111111 DATA &1000000000000001 DATA &1000000000000001 DATA &1000011111100001 DATA &1000000000100001 DATA &1000000000100000 DATA &1000000000100000 DATA &1000000000100001 DATA &1000011111100001 DATA &1000000000000001 DATA &1000000000000001 DATA &1111111111111111 room1: DATA &1111111111111111 DATA &1000000000000001 DATA &1000000000000001 DATA &1000010000100001 DATA &1000010000100001 DATA &1000010000100001 DATA &1000010000100001 DATA &1000010000100001 DATA &1000010000100001 DATA &1000000000000001 DATA &1000000000000001 DATA &1111110000111111 ' ' Bitmaps used in the game ' drawings: BITMAP "#..##..#" BITMAP "########" BITMAP ".#.##.#." BITMAP ".######." BITMAP "..####.." BITMAP "..#..#.." BITMAP "..#..#.." BITMAP ".##..##." BITMAP "...##..." BITMAP "...##..." BITMAP "..####.." BITMAP "..#..#.." BITMAP "..####.." BITMAP "..####.." BITMAP ".######." BITMAP "##.##.##" BITMAP "...##..." BITMAP "...##..." BITMAP ".######." BITMAP "...##..." BITMAP "...##..." BITMAP "..####.." BITMAP "..#..#.." BITMAP ".##..##." BITMAP ".##....." BITMAP "###....." BITMAP ".##....." BITMAP ".#######" BITMAP ".######." BITMAP ".##..##." BITMAP ".##..##." BITMAP "###.###." game2.bas 2 Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 4, 2018 Author Share Posted December 4, 2018 Wow! That does make the process so much quicker. I'm really glad I learned what the binary and hex stuff was about too. Now I know how to do both and hoe much effort has gone into IntyBASIC to make it so robust as a programming platform. Thanks for sharing the tip about the binary numbers! Blaine 1 Quote Link to comment Share on other sites More sharing options...
jlew715 Posted December 9, 2018 Share Posted December 9, 2018 (edited) The $8000 represents bit 15 on a 16-bit word. The expression "#line and $8000" tests to see if bit 15 is set by masking[/] that bit and isolating it from the rest of the word . If so, it prints a particular sequence of characters. This is driving me nuts - I totally understand the result of this, but I can't understand how it works! Converting to binary, that line becomes IF #line AND &1000000000000000 THEN PRINT [whatever] So, say my first DATA line is &1000000000000001. During the first iteration of the loop, we would be comparing: IF &1000000000000001 AND &1000000000000000 THEN PRINT [whatever] I understand that because the leftmost bits are both 1, the AND comparison evaluates as true, and my [whatever] is printed. What I don't understand is how this AND comparison is only checking bit 15, and ignoring all the other bits. How does comparing the two Words in this way make the masking happen? Edited December 9, 2018 by jlew715 Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 9, 2018 Author Share Posted December 9, 2018 Hi jlew715! Wow, I get to help someone along with IntyBASIC for the first time. That's pretty cool. I don't have a complete answer for your questions. Here's what I can tell you for sure, though. I'm building a custom game, based on the game2.bas framework. I've built 10 mazes so far, and will be adding many more. I've found that I can assign the 0 bit or bits along the border walls wherever I want and the formula will put the /95 blank space in the right place. I've put them on all four border walls and each one worked as expected, including checking for maze exits. So, that doesn't answer your question about how the $8000 (the 1000000000000000 binary string) checks for bit 15. However, it does at least help understand that you can use it to your advantage to put maze exits wherever you want them along the border. Nanochess (Oscar) wrote this code, so he should be able to help you along. Dz also knows this stuff quite well and should be able to chime in. Stay in touch with me along the way, if you'd like. I've found some interesting ways to make the game2.bas code do some very interesting things to add value to the gameplay. I'm only a month in to learning it all, but I will share whatever I can whenever I can. That's what makes this stuff fun and this community great. - Blaine Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 9, 2018 Share Posted December 9, 2018 (edited) On 12/8/2018 at 9:59 PM, jlew715 said: This is driving me nuts - I totally understand the result of this, but I can't understand how it works! Converting to binary, that line becomes IF #line AND &1000000000000000 THEN PRINT [whatever] So, say my first DATA line is &1000000000000001. During the first iteration of the loop, we would be comparing: IF &1000000000000001 AND &1000000000000000 THEN PRINT [whatever] I understand that because the leftmost bits are both 1, the AND comparison evaluates as true, and my [whatever] is printed. What I don't understand is how this AND comparison is only checking bit 15, and ignoring all the other bits. How does comparing the two Words in this way make the masking happen? Hi, jlew715, I'll try to answer your question. Not knowing really the level of understanding and experience you already have in bitwise or boolean logic operations, please forgive me if some of the information below is too basic for you. Feel free to skip ahead to the "Bitwise Masking" section or ask any further relevant questions. In any case, here's a neat tutorial on binary numbers. Binary Number System In computer programming, any value -- whether it be a number, a character, a string, a pointer, etc. -- is stored internally as a series of binary values. The reason for this is because in the Binary number system, all values are represented by ones and zeros, which translate perfectly to the electrical signals that flow through electronic computers. Inside a computer, when electric current flows through a circuit it typically represents a one, and when no current flows, it represents a zero. Thus, the millions of transistors inside a computer's CPU act as "switches" which turn on and off electrical current to various parts. Groups of these parts then individually can combine to represent entire numerical values, and these in turn combine to represent more complex values, such as textual strings. It is not important really to know how all of that works inside the computer, but it is useful to understand that no matter what you are dealing with in your computer program -- an integer, a floating point number, a character, or anything at all -- it is internally just a bunch of binary bits -- ones and zeros -- strung together. Bitwise Operators Knowing that all our program variable values are internally just binary numbers also allows us to be clever about their make up. You see, binary values have some very neat unique properties which we can exploit at the bit level. Think of a bit as a "binary digit" in the same way we think of a "decimal digit" -- only that in decimal, our digits are from 0 to 9, and in binary our digits are from 0 to 1. Now, imagine how we can say things like "every decimal number ending in 0 is divisible by 10," or "every decimal number divisible by 2 is an even number," or "every decimal number ending in 5 is just half-way to the next power of ten," etc. All of these are neat properties that allow us to manipulate decimal numbers efficiently with just some clever maths. The same applies to binary numbers, except that the neat properties are related to the powers of 2 (remember, decimal = powers of 10; binary = powers of 2). We call these neat manipulations at the bit level, "bitwise operations," and they form the primitive operating mode of computers themselves. Like mentioned above, because all the values in our programs are just internally binary numbers (even though this is abstracted from us sometimes by calling them "integers" or "characters" or whatever), we can exploit their special binary properties using bitwise operations. Boolean Algebra A clever chap some 200 years ago came up with a way of formalizing the language of logic in order to prove inferences and deductions. This was not really computer program logic, but logic in the philosophical sense. He came up with a symbolic language to express logical statements based on mathematics called now Boolean Algebra. In this formal expression you could say something like: A = Fruit B = Food C = Apple Fruits are food --> A = B Apple is a fruit --> C = A Apple is food --> C = B With his algebra, you no longer had to prove that an apple is a food directly. As long as you can prove that fruits are food and that an apple is a fruit, the transitive property of algebra would positively prove by inference that an apple is food. Apart from the transitive, and just like Algebra, Boolean Algebra defines all sorts of useful properties and "laws." For instance: Associative Commutative Identity Distributive Complement etc. Anyway, this symbolic language has rules and principles and properties that are very useful for manipulating multiple logical statements together in a formal, mathematical way. Like algebra, you string your statements together in an equation and operate on the terms one or two at a time. The basic Boolean operators are: Conjunction (AND) => Only when two terms are true, is the output true. Disjunction (OR) => When at least one of the terms is true, the output is true. Negation (NOT) => The output is the logical opposite of the term. As you can imagine, operating one or two terms at a time is perfect for the binary operations of a computer. Thus, bitwise operators perform Boolean Arithmetic operations on individual bits of a binary value. NOTE: These are easier to remember than you may think at first. Do not think of them as algebraic or numeric expressions, but as just regular, every day logical statements: AND: IF Anne is blonde AND blondes are stupid THEN Anne is stupid The conclusion can only be true if both terms are true. Any falsehood will result in the conclusion being false. OR: IF you have money OR I have money THEN we go to lunch The conclusion is contingent on the truth of any of the two terms. Either one being true will make the outcome true. NOT: Anne is NOT stupid The conclusion is the opposite of the term. In this case the term is "stupid," and the conclusion is that Anne is the opposite of stupid, or "NOT stupid." Bitwise Masking For the purposes of your original question, we need to describe how we operate on individual bits within a binary number. This is an interesting problem, but one with a very simple solution. If binary numbers are a bunch of binary digits, and we want to tell the computer to manipulate only a particular group of them, how do we do that? Well, we must first isolate those bits from the rest so that the outcome only applies to our bits of interest. This is called "masking" because it works in the same way you use a stencil or tape or filter to mask out the light shining out of lamp, and only let through parts of it. Masking is so easy, it's silly once you figure it out. All we need to do is exploit the "AND" operator properties. As mentioned above, AND operates on two terms and says "if both are true, the output is true, otherwise it is false." What this means is that by definition, everything ANDed with a false value results in false. Let's take a look: 1 1 1 1 1 1 1 1 : Binary number 1 1 1 1 0 0 0 0 : Mask the top four digits --------------- 1 1 1 1 0 0 0 0 Notice that the mask causes the last four digits to be zero just because they are not covered by the mask. It does not matter what those bits are in the original value, they will be turned to zero automatically. Now, consider this example: 1 0 1 0 1 0 1 0 : Binary number 1 1 1 1 0 0 0 0 : Mask the top four digits --------------- 1 0 1 0 0 0 0 0 See what happened? Take a look at the top four digits of the output: They are identical to the top four digits of the original value! That's what a bit-mask gives you: Anything in the mask which is a zero will be ignored and turned to zero, and everything which is a one will return the original value! -- letting the "light" shine through the ones. Neat, uh? Sure, we could be sticklers for exactness and say that the mask is applied bitwise, or bit-by-bit, to the input value, and therefore the output is the result of the individual ANDing of each bit to its corresponding bit on the mask. Thus: 1 0 1 0 1 0 1 0 : Binary number 1 1 1 1 0 0 0 0 : Mask the top four digits --------------- 1 0 1 0 0 0 0 0 | | | | | | | | | | | | | | | '-> 0 AND 0 = [0] | | | | | | '---> 1 AND 0 = [0] | | | | | '-----> 0 AND 0 = [0] | | | | '-------> 1 AND 0 = [0] | | | '---------> 0 AND 1 = [0] | | '-----------> 1 AND 1 = [1] | '-------------> 0 AND 1 = [0] '---------------> 1 AND 1 = [1] V | '-----> [1 0 1 0 0 0 0 0] But, since the properties of the AND operator apply equally over any value, we can take the shortcut and just state it like this: Zero bits in the mask will discard bits on the original Ones in the mask will let the original bits through OK, so let's go to your original question, which was, how does the following statement work? IF #line AND &1000000000000000 THEN PRINT [whatever] Well, let's apply what we have discussed above. First, the fact that we are ANDing a constant value should stand out to you and scream "masking!" Whether this is the exact purpose or not, because that's how bitwise masking works, the results will be the same. Second, everything that is a zero in the mask will be ignored and turned to zero. That tells us that it doesn't matter what value is in the variable #line, most of those bits will be discarded and ignored. Third, what's left? The single bit in the mask means that only that bit will be allowed to go through, and that the resulting value will be exactly the same as that bit in the original value. Essentially, the mask is isolating that bit by returning it and only it. The output of the IF/THEN statement becomes whether that particular bit in the original value is one (true) or zero (false). This will consequently drive whether the THEN clause will be executed or not. Here are some additional masks to give you an idea of how to reason over this stuff. $FF00 = %1111111100000000 : Isolate the high-order byte in a 16-bit word. $00FF = %0000000011111111 : Isolate the low-order byte in a 16-bit word. $8000 = %1000000000000000 : Isolate the Most Signifiant Bit (MSB), indicating whether the value is positive or negative. $0001 = %0000000000000001 : Isolate the Least Significant Bit (LSB), indicating whether the value is odd (1) or even (0). $07F8 = %0000011111111000 : Isolate the "card index" in a 16-bit BACKTAB word. There you have it, bitwise masking, in all its binary and boolean glory. I hope this helps. -dZ. Edited October 18, 2021 by DZ-Jay 3 Quote Link to comment Share on other sites More sharing options...
nanochess Posted December 9, 2018 Share Posted December 9, 2018 This is driving me nuts - I totally understand the result of this, but I can't understand how it works! Converting to binary, that line becomes IF #line AND &1000000000000000 THEN PRINT [whatever] So, say my first DATA line is &1000000000000001. During the first iteration of the loop, we would be comparing: IF &1000000000000001 AND &1000000000000000 THEN PRINT [whatever] I understand that because the leftmost bits are both 1, the AND comparison evaluates as true, and my [whatever] is printed. What I don't understand is how this AND comparison is only checking bit 15, and ignoring all the other bits. How does comparing the two Words in this way make the masking happen? It's easy. Once it checked the bit for the square then #line is multiplied by 2. This means the next bit is then available for checking. Multiplying by 2 is equivalent to shifting left by one bit. I hope this helps. Quote Link to comment Share on other sites More sharing options...
jlew715 Posted December 9, 2018 Share Posted December 9, 2018 There you have it, bitwise masking, in all its binary and boolean glory. I hope this helps. -dZ. This is exactly what I was looking for! Thank you so much for the detailed and speedy reply. I have a fair amount of experience with modern, higher-level languages (Java, JS, Lua, etc.) but that only goes so far. Thanks again! Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted December 9, 2018 Share Posted December 9, 2018 This is exactly what I was looking for! Thank you so much for the detailed and speedy reply. I have a fair amount of experience with modern, higher-level languages (Java, JS, Lua, etc.) but that only goes so far. Thanks again! Sure thing, it's my pleasure. Modern languages encapsulate and abstract away most of these details. You can still do the same things in Java, but for the most part, there are different and much better patterns to address the same problems that work at a much higher cognitive level. For instance, in Java, you wouldn't need to pack multiple flags into a single 16-bit field variable; you just create different boolean object properties and access them individually. Easy peasy. In IntyBASIC, or any any vintage computer system, it becomes too costly to treat each individual boolean value as a separate variable. With such severe memory constraints, using an entire 16-bit memory word for a single true-or-false flag seems rather wasteful. You'll find a lot of this sort of magic used in Intellivision programs, and hopefully you'll be able to apply the same tricks yourself on your own programs. Just, don't be afraid to ask, and if an answer does not make sense to you, or you feel you need additional help, don't be afraid to ask again. -dZ. Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 9, 2018 Author Share Posted December 9, 2018 Hi, everyone! I have another quick question related to the room drawing process. I am adding new rooms to the game (10 so far). How would I make the game choose a random room number at each redraw instead of doing them in sequence? Right now, I just have ten if then statements exactly like the ones used to draw the two sample rooms. How would I make it where the room selection is random each redraw? Preferably, it would be best not to repeat any of the rooms throughout the process, if possible. I've taken a few shots at this by trying to use a variable, the RANDOM statement, and a data list with the numbers 1-10 in it, separated with commas. It drew random blue blocks everywhere and never generated the monsters. Thanks!Blaine Quote Link to comment Share on other sites More sharing options...
carlsson Posted December 9, 2018 Share Posted December 9, 2018 I would probably change the statement room = room+1 to something that involves RANDOM and leave the IF statements as they are. Or even better, set up an array of 8-bit integers that have as many slots as you have rooms, and on initializaiton assign rooms. Something like this (untested) which though eats some valuable variable space unless you can find a smarter solution: DIM room_avail(10), room_order(10) [..] restart: FOR i=0 TO 9:room_avail(i)=1:NEXT FOR i=0 TO 9 DO:y=RANDOM(10):LOOP UNTIL room_avail(y)=1 room_order(i)=y room_avail(y)=0 NEXT [..] load_room: IF room_order(room)=0 THEN ... IF room_order(room)=1 THEN ... Make adjustments and corrections as required. The assignment of rooms could be done in a slower way that uses less variables, by cycling through a second loop FOR k=0 TO i that checks all previous entries in room_order so the selected room already hasn't been assigned. Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 10, 2018 Author Share Posted December 10, 2018 Hello again! Well, I was able to add the code, and it made the game start on the next sequential level each time it restarted. I'm not sure why it didn't pass a random number to the level start variable, though. In other words, if the game started on level 1, when the player died, the game would restart on level 2. Then when the player died, it would restart on level 3. Repeated the process until level 10, where it restarted at level 1. So it made the levels start on a different number sequentially, just not randomly. Another anomaly that happened: I think it looked for a room0, which it didn't find, and randomly generated a gibberish room. Once that was cleared, it went on to room1. I'm sure this has to do with the difference between whole numbers and integer numbers. When I tried to relabel the rooms as 0-9, and adjusted the random number generation to 9, the compiler would say things like it couldn't find room8 and fail to compile. So, as it stands, I have the code put in, the game creates a jibberish level 0, then sequentially restarts at the last level it started on plus one. Where do I go from here? Thanks!Blaine Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 10, 2018 Author Share Posted December 10, 2018 I should also mention that the junk screen (maze0?) only shows the first time through the loop. The other times, it goes back to maze1, as instructed in the code loop. Thanks!Blaine Quote Link to comment Share on other sites More sharing options...
nanochess Posted December 10, 2018 Share Posted December 10, 2018 It's hard to decipher without looking at your room selection code and random generation. Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 10, 2018 Author Share Posted December 10, 2018 Here's the code at it sits right now. I still have a copy that just runs them sequentially from room 1 onward. Just trying to learn new ways to make gameplay more enduring and not redundant because of my coding. Thanks! DIM room_avail(9), room_order(9) startgame: WAIT WAIT DEFINE DEF00,4,drawings restart: WAIT #score=1 FOR i=0 TO 9:room_avail(i)=1:NEXT FOR i=0 TO 9 DO:y=RANDOM(9):LOOP UNTIL room_avail(y)=1 room_order(i)=y room_avail(y)=1 NEXT REM Play the music for the game PLAY FULL PLAY solarsailer load_room: if room=1 then restore room1:#monster=SPR00 + SPR_RED if room=2 then restore room2:#monster=SPR00 + SPR_RED if room=3 then restore room3:#monster=SPR00 + SPR_RED if room=4 then restore room4:#monster=SPR00 + SPR_RED if room=5 then restore room5:#monster=SPR00 + SPR_RED if room=6 then restore room6:#monster=SPR00 + SPR_RED if room=7 then restore room7:#monster=SPR00 + SPR_RED if room=8 then restore room8:#monster=SPR00 + SPR_RED if room=9 then restore room9:#monster=SPR00 + SPR_RED if room=10 then restore room10:#monster=SPR00 + SPR_RED Well, if you read this far, you also might have noticed a small hint at what direction this project is taking. Quote Link to comment Share on other sites More sharing options...
carlsson Posted December 10, 2018 Share Posted December 10, 2018 You forgot to change the IF statements so they say "IF room_order(room)=1" and so on. Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 10, 2018 Author Share Posted December 10, 2018 Yes! That fixed it up right away. Thank you! If there's one more thing that would be of tremendous help, it would be helping me set up that loop that makes sure the same level isn't shown twice. I'm just not quite there with the coding part to make that work. Once I have it going for a first time, though, I'll be able to use it again in the future through the example. Thanks!Blaine Quote Link to comment Share on other sites More sharing options...
carlsson Posted December 10, 2018 Share Posted December 10, 2018 D'oh! A bug in my code above. Once you have assigned a room, you should set room_avail(y)=0 to make sure it isn't assigned once more. Quote Link to comment Share on other sites More sharing options...
blainelocklair Posted December 10, 2018 Author Share Posted December 10, 2018 I put the statement after the if room = # then statements, at the end of the whole list, once. It still doesn't randomize them without repetition. Here's what I did: load_room: IF room_order(room)=1 then restore room1:#monster=SPR00 + SPR_RED IF room_order(room)=2 then restore room2:#monster=SPR00 + SPR_RED IF room_order(room)=3 then restore room3:#monster=SPR00 + SPR_RED IF room_order(room)=4 then restore room4:#monster=SPR00 + SPR_RED IF room_order(room)=5 then restore room5:#monster=SPR00 + SPR_RED IF room_order(room)=6 then restore room6:#monster=SPR00 + SPR_RED IF room_order(room)=7 then restore room7:#monster=SPR00 + SPR_RED IF room_order(room)=8 then restore room8:#monster=SPR00 + SPR_RED IF room_order(room)=9 then restore room9:#monster=SPR00 + SPR_RED IF room_order(room)=10 then restore room10:#monster=SPR00 + SPR_RED room_avail(y)=0 Did I put it in the wrong place? Probably, since it isn't working. Thanks again for all of your help! I really do appreciate it. Blaine Quote Link to comment Share on other sites More sharing options...
carlsson Posted December 11, 2018 Share Posted December 11, 2018 The assignment loop most likely should read like this: FOR i=0 TO 9 DO:y=RANDOM(9):LOOP UNTIL room_avail(y)=1 room_order(i)=y room_avail(y)=0 NEXT Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.