QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: qbkiller101 on March 24, 2020, 05:54:22 am

Title: QBasic OS
Post by: qbkiller101 on March 24, 2020, 05:54:22 am
Hi,
I’m an amateur QBasic programmer and I’m developing a text-based operating system like thing but I’m stuck at two things, 1) when a user types a command (like ms-dos) the os responds with the required action but I can't put an if or case statement with all possible commands after all input statements as that would be too long. 2) how to create a virtual machine that would boot with the .bas file or with qb64 in which I will run the file. Please help.

(Please don't make fun just tell me how to as everyone makes fun for creating a QBasic OS)
Title: Re: QBasic OS
Post by: TempodiBasic on March 24, 2020, 07:35:05 am
Hi qbkiller101

welcome to the forum of QB64

just about your issue... I must say 3 simple concepts:

1. QBasic and also QB64 are not the more suitable language for build up an Operative System.
Think that an OS must manage file system, RAM, VideoRAM, hardware devices .... often at this level you must manage bits and bytes!
Moreover also the simplest OS must be efficient and  fast.... It seems that the walking from Basic Source code to ASM pseudocode to binary code is not so linear and easy to manage as result in terms of speed and efficacy per QB/Qbasic!
In QB64 you must put in this line  of compiling  the translation from QB64 to C++ and then the compiling of C++ to bynary code. Another extra step that can make difference in results.

2.
about
Quote
I can't put an if or case statement with all possible commands after all input statements as that would be too long

what kind of project have you raised up for Qbasic OS?
I think that there are more commands in QB64 then in your thought Qbasic OS... and the parser of QB64 can manage it istantanely (see syntax check while you're typing code)

3.
about
Quote
how to create a virtual machine that would boot with the .bas file or with qb64 in which I will run the file.


This is an ambitious goal that lets me think about Commodore 64 that I remember has a BASIC in its ROMS.
A QB64 Machine like the Java Machine that all we have on our PC, notebook, netbook , smartphone etc etc.

In this case yoo must project a layer of interface between your QB64 machine and the other  OS that hosts the QB64 machine. An API as DLL or similar to translate (ask and get feedback) the requests of QB64 machine to Windows or/and  MAC or/and Linux  or/and Android.

My suggestions are:
for QB64 OS alone...study the hardware on  common machine and see how you can manage using QB64
for QB64 virtual machine...
study the service that the host OS uses to manage hardware and how you can access to those service to build an interface for QB64 machine. Then make a  project of a minimal Qbasic OS.
You can study the Commodore system to have an example.
These are my two cents.
More experienced coders can give you more suggestions and tips.

C64 OS https://en.wikipedia.org/wiki/Commodore_64#BASIC (https://en.wikipedia.org/wiki/Commodore_64#BASIC)
Title: Re: QBasic OS
Post by: luke on March 24, 2020, 09:23:37 am
I wrote a quick shell program:
Code: [Select]
$CONSOLE:ONLY
_DEST _CONSOLE
IF NOT _DIREXISTS("/var/lib/qenv") THEN MKDIR "/var/lib/qenv"
CHDIR "/var/lib/qenv"

PRINT "READY"

DO
    PRINT "> ";
    LINE INPUT in$
    REDIM parts$(0)
    split in$, " ", parts$()
    IF UBOUND(parts$) = -1 THEN _CONTINUE
    SELECT CASE LCASE$(parts$(0))
        CASE "echo"
            PRINT join$(parts$(), " ", 1)
        CASE "dir"
            SHELL "ls"
        CASE "cd"
            CHDIR "/var/lib/qenv/" + parts$(1)
        CASE "write"
            OPEN parts$(1) FOR OUTPUT AS #1
            PRINT #1, join$(parts$(), " ", 2)
            CLOSE #1
        CASE "type"
            OPEN parts$(1) FOR BINARY AS #1
            s$ = SPACE$(LOF(1))
            GET #1, , s$
            PRINT s$;
            CLOSE #1
        CASE "del"
            KILL parts$(1)
        CASE ELSE
            PRINT "?"
    END SELECT
LOOP

SUB split (in$, delimiter$, result$())
    REDIM result$(-1)
    start = 1
    DO
        WHILE MID$(in$, start, 1) = delimiter$
            start = start + 1
            IF start > LEN(in$) THEN EXIT SUB
        WEND
        finish = INSTR(start, in$, delimiter$)
        IF finish = 0 THEN finish = LEN(in$) + 1
        REDIM _PRESERVE result$(0 TO UBOUND(result$) + 1)
        result$(UBOUND(result$)) = MID$(in$, start, finish - start)
        start = finish + 1
    LOOP WHILE start <= LEN(in$)
END SUB

FUNCTION join$ (in$(), delimiter$, offset)
    result$ = in$(LBOUND(in$) + offset)
    FOR i = LBOUND(in$) + 1 + offset TO UBOUND(in$)
        result$ = result$ + delimiter$ + in$(i)
    NEXT i
    join$ = result$
END FUNCTION
Then did some cruel and unusual things to a minimal Debian install in VirtualBox. See the resulting screen capture.

If anything, I'd say it's rather convincing.
Title: Re: QBasic OS
Post by: TempodiBasic on March 24, 2020, 11:00:34 am
Thanks Luke
the video is very interesting and impressive...


MKDIR, CHDIR, RMDIR, KILL, SHELL cmdline, NAME , FILES are the built-in file system of Qbasic to which we can add _FILEEXISTS of QB64.
The rest stands to the developer of Qbasic OS.

PS about FILE....
it is a very pity to have a internal command that works only just the old Qbasic command (useful in the old system where it is impossible to think to have so more files on the supports) and its output isn't addressable to other thing than screen... no clipboard , no file.
But do who QB64 coder  likes  get directory content into clipoboard or file? Only just to a lazy coder like me. ;)
Title: Re: QBasic OS
Post by: qbkiller101 on March 25, 2020, 05:58:30 am
Sorry but as i have told
I’m an amateur QBasic programmer
[/font]
Please can luke explain the code as i cant understand
Code: QB64: [Select]
  1. IF NOT _DIREXISTS("/var/lib/qenv") THEN MKDIR "/var/lib/qenv"
  2. CHDIR "/var/lib/qenv"
  3.  
  4. PRINT "READY"
and
Code: QB64: [Select]
  1. SUB split (in$, delimiter$, result$())
  2.     REDIM result$(-1)
  3.     start = 1
  4.     DO
  5.         WHILE MID$(in$, start, 1) = delimiter$
  6.             start = start + 1
  7.             IF start > LEN(in$) THEN EXIT SUB
  8.         WEND
  9.         finish = INSTR(start, in$, delimiter$)
  10.         IF finish = 0 THEN finish = LEN(in$) + 1
  11.         REDIM _PRESERVE result$(0 TO UBOUND(result$) + 1)
  12.         result$(UBOUND(result$)) = MID$(in$, start, finish - start)
  13.         start = finish + 1
  14.     LOOP WHILE start <= LEN(in$)
  15.  
  16. FUNCTION join$ (in$(), delimiter$, offset)
  17.     result$ = in$(LBOUND(in$) + offset)
  18.     FOR i = LBOUND(in$) + 1 + offset TO UBOUND(in$)
  19.         result$ = result$ + delimiter$ + in$(i)
  20.     NEXT i
  21.     join$ = result$
and a simple explanation of the middle part
you can email if you like
omerhijazi@outlook.com


Title: Re: QBasic OS
Post by: qbkiller101 on March 25, 2020, 06:00:27 am
I'm an amateur, amateur QBasic programmer and I'm not even good in loops
So please a little detailed explanation
Title: Re: QBasic OS
Post by: TerryRitchie on March 25, 2020, 12:13:30 pm
I'm an amateur, amateur QBasic programmer and I'm not even good in loops
So please a little detailed explanation

Welcome to the forum! :)

In your first post you state that you are developing a text based OS. Most code (if not all code) people are going to post to help you with your journey is going to be at least a little above beginner level. Perhaps, as a suggestion, before starting with something as ambitious as a text based OS you go through some programming tutorials to get a feel for what programming is and how to structure code.

Here are some Qbasic tutorials to get you started:

[ Invalid YouTube link ]&feature=emb_logo

Here are some totorials I created for QB64:

http://qb64sourcecode.com/

I wrote those tutorials back when QB64 was hosted on [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] so disregard any links you may see that point there.

Since Qbasic is a direct descendant of QB64 what you learn in those tutorials will work 100% for you in QB64.

I'm not trying to be flippant or discourage you in any way, I'm very happy someone else has decided to learn programming using QB64. It's just that without a foundation in the language and coding in general I'm afraid you'll get frustrated very quickly and decide to leave programming entirely.

Go through the tutorials and post questions you have about what you learned. You'll be surprised at how quickly the BASIC language can be learned.

Sincerely, Terry.
Title: Re: QBasic OS
Post by: bplus on March 25, 2020, 12:41:36 pm
I am not Luke (I am his father ha, ha!) but here are some comments
Code: QB64: [Select]
  1. ' ^^^^^^^^^^^^^^ set up console window
  2. _DEST _CONSOLE ' <<< send output to console window
  3. IF NOT _DIREXISTS("/var/lib/qenv") THEN MKDIR "/var/lib/qenv" ' <<< if the directory (folder) does not exit make it
  4. CHDIR "/var/lib/qenv" ' <<< now change the working directory to that folder  if you know DOS you know current directory  CD command
  5.  
  6. PRINT "READY"
  7.  
  8.  
  9.  

Code: QB64: [Select]
  1. 'say we have
  2. weekDays$ = "Moonday Tuesday Wednesday Thursday Friday Saturday Sunday" ' ha Moonday
  3. 'say the delimiter is a space
  4. ' call the split sub
  5. REDIM daynames$(0)  ' split needs to work with dynamic arrays (you can change their size and dim with REDIM not DIM)
  6. split weekDays$, " ", daynames$()
  7. 'result
  8. PRINT "DayNames array:"
  9. FOR i = LBOUND(daynames$) TO UBOUND(daynames$)
  10.     PRINT i, daynames$(i)
  11.  
  12. ' split is a parser SUB
  13. ' this sub takes a string as input =in$ and splits it into segments according to the delimiter often a space
  14. ' these fragments are put into the string array result$()
  15. SUB split (in$, delimiter$, result$())
  16.     REDIM result$(-1) ' <<< wants base zero so starts below  and clears array contents
  17.     start = 1
  18.     DO
  19.         WHILE MID$(in$, start, 1) = delimiter$
  20.             start = start + 1
  21.             IF start > LEN(in$) THEN EXIT SUB
  22.         WEND
  23.         finish = INSTR(start, in$, delimiter$)
  24.         IF finish = 0 THEN finish = LEN(in$) + 1
  25.         REDIM _PRESERVE result$(0 TO UBOUND(result$) + 1)
  26.         result$(UBOUND(result$)) = MID$(in$, start, finish - start)
  27.         start = finish + 1
  28.     LOOP WHILE start <= LEN(in$)
  29.  
  30. ' this SUB reverses what Split did taking part of an array starting at offset item and making a long
  31. 'string of those remaining items from offset on  << EDIT this line for better interpretation
  32. FUNCTION join$ (in$(), delimiter$, offset)
  33.     result$ = in$(LBOUND(in$) + offset)
  34.     FOR i = LBOUND(in$) + 1 + offset TO UBOUND(in$)
  35.         result$ = result$ + delimiter$ + in$(i)
  36.     NEXT i
  37.     join$ = result$
Title: Re: QBasic OS
Post by: Qwerkey on March 25, 2020, 12:43:37 pm
Very helpful suggestions from Terry.
Title: Re: QBasic OS
Post by: qbkiller101 on March 25, 2020, 02:43:09 pm
Extremely thankful for your help guys
just showing you
here's the prototype sorta thing.
before seeing the code run the .exe file and think how nice or bad the code will look like (you'll be shocked)
anyways... after taking in all the advice I'll update the code.
and if you want you can edit it to show each other
freeware sorta thing... you know
why would an 11-year-old want to copyright or something???!

this is the os
https://drive.google.com/open?id=19tvV0Pq_L3-ZdGQvuO0HzFwGsjYjWL9R
Title: Re: QBasic OS
Post by: bplus on March 25, 2020, 03:19:57 pm
Uh, how does it know?

OK spoiler alert:
Code: QB64: [Select]
  1. unc$ = "abc"
  2. pwc% = 123
  3.  

Ok it works played a nice game of TTT
Title: Re: QBasic OS
Post by: qbkiller101 on March 26, 2020, 07:41:44 am
Oh, I forgot to mention two things.
1) you need to enter the password and username you like in unc and pwc
2) see the code of TTT
Code: QB64: [Select]
  1. PRINT "Credits"
  2. PRINT "-------"
  3. PRINT "This game was created by Paul Meyer in the year 2007."
  4. PRINT: PRINT "Graphics by TheBob"
  5. PRINT: PRINT "Improved mouse driver, modularity, machine play-to-win";
  6. PRINT " by QBasic Mac"
  7. PRINT: PRINT "History:"
  8. PRINT "http://www.network54.com/Forum/190883/message/1175106480"
  9. PRINT "This is freeware, you may change this as much as you want"
  10. PRINT "as long as you don't claim it as yours."
  11.  

Title: Re: QBasic OS
Post by: qbkiller101 on March 26, 2020, 07:43:15 am
Unfortunately the website doesnt exist
Title: Re: QBasic OS
Post by: SMcNeill on March 26, 2020, 12:33:18 pm
Unfortunately the website doesnt exist

Network54 still exists.  Their forums simply got absorbed by TapaTalk, like tons of other old ones.  You can probably find your old link here somewhere: https://www.tapatalk.com/groups/qbasic/index.php
Title: Re: QBasic OS
Post by: EricE on March 26, 2020, 01:29:21 pm
Is this the code?

Code: QB64: [Select]
  1. DECLARE SUB Winner (Lineup AS INTEGER)
  2. DECLARE SUB ShowWin (b1 AS INTEGER, b2 AS INTEGER, b3 AS INTEGER)
  3. DECLARE SUB GetUserSignal ()
  4. DECLARE SUB EnableMouse (c%)
  5. DECLARE SUB DrawSCREEN ()
  6. DECLARE SUB xo (Row%, Col%, symbol%)
  7.  
  8. DIM SHARED False AS INTEGER, True AS INTEGER: True = NOT False
  9. DIM SHARED SymbolBOX(6000) AS INTEGER '<---NOTE
  10.  
  11. DIM SHARED cH AS INTEGER: 'Cursor Position Horizontal
  12. DIM SHARED cV AS INTEGER: 'Cursor Position Vertical
  13. DIM SHARED click AS INTEGER: ' 0=no click, 1=left click, 2=right
  14. ' EnableMouse 1 = Turn cursor on, return coordinates
  15. ' EnableMouse 0 = Turn cursor off in order to draw stuff, etc.
  16. DIM SHARED cC AS STRING: 'User pressed key
  17. ' GetUserSignal will set return cC or will return Click
  18.  
  19. DIM WhoWon AS INTEGER
  20. DIM MadeAMove AS INTEGER, MovesMade AS INTEGER
  21.  
  22. ' ----------------------------------------------------------
  23. ' Title Screen (Main Program)
  24. ' -----------------------------------------------------------
  25. DIM Command AS INTEGER, Hard AS INTEGER
  26. GOSUB InitializeScreen
  27. DO: GetUserSignal: LOOP UNTIL click = 1
  28. GOSUB FindClickedCommand
  29. SELECT CASE Command
  30. CASE 1:
  31. Hard = False
  32. WhoWon = 0
  33. GOSUB PlayGame
  34. GOSUB ShowWhoWon
  35. GOSUB InitializeScreen
  36. CASE 2:
  37. Hard = True
  38. WhoWon = 0
  39. GOSUB PlayGame
  40. GOSUB ShowWhoWon
  41. GOSUB InitializeScreen
  42. CASE 3:
  43. GOSUB DoHelp
  44. GOSUB InitializeScreen
  45. CASE 4:
  46.  
  47. ' ----------------------------------------------------------
  48. ' Game Screen
  49. ' -----------------------------------------------------------
  50. DIM SHARED zX(9) AS INTEGER: ' Where all X's are placed
  51. DIM SHARED zO(9) AS INTEGER: ' Where all O's are placed
  52. DIM SHARED zE(9) AS INTEGER: ' Where empty squares are
  53. DIM theRow AS INTEGER, theColumn AS INTEGER, theBox AS INTEGER
  54.  
  55. FindClickedPosition:
  56. CONST Delta = 4
  57. theRow = 0: theColumn = 0: theBox = 0
  58. CASE IS < 170 + Delta: RETURN
  59. CASE IS < 269 - Delta: theColumn = 1
  60. CASE IS < 269 + Delta: RETURN
  61. CASE IS < 368 - Delta: theColumn = 2
  62. CASE IS < 368 + Delta: RETURN
  63. CASE IS < 467 - Delta: theColumn = 3
  64. CASE IS < 91 + Delta: RETURN
  65. CASE IS < 190 - Delta: theRow = 1
  66. CASE IS < 190 + Delta: RETURN
  67. CASE IS < 289 - Delta: theRow = 2
  68. CASE IS < 289 + Delta: RETURN
  69. CASE IS < 388 - Delta: theRow = 3
  70. theBox = (3 * (theRow - 1)) + theColumn
  71.  
  72. ' ----------------------------------------------------------
  73. ' Play Game
  74. ' -----------------------------------------------------------
  75. PlayGame:
  76. DrawSCREEN 'draw the screen and create X and O symbols.
  77. FOR i = 1 TO 9: zO(i) = False: zX(i) = False: zE(i) = True: NEXT i
  78. MovesMade = 0
  79. GetUserSignal
  80. IF click THEN
  81. MadeAMove = False
  82. GOSUB MakeX
  83. IF MadeAMove THEN
  84. WhoWon = 1: GOSUB ComputeWin: IF WhoWon = 1 THEN RETURN
  85. t% = 0
  86. FOR i = 1 TO 9: t% = t% + zX(i): NEXT i
  87. IF t% = -5 THEN WhoWon = 0: RETURN
  88. MovesMade = MovesMade + 1
  89. GOSUB MakeO
  90. WhoWon = 2: GOSUB ComputeWin: IF WhoWon = 2 THEN RETURN
  91. IF cC = "d" OR cC = CHR$(27) THEN WhoWon = 3
  92. IF WhoWon > 0 THEN RETURN
  93.  
  94. MakeX:
  95. GOSUB FindClickedPosition
  96. IF theBox = 0 THEN RETURN
  97. IF NOT zE(theBox) THEN RETURN
  98. xo theRow, theColumn, 1: ' Places an X
  99. zX(theBox) = True: zE(theBox) = False
  100. MadeAMove = True
  101.  
  102. MakeO:
  103. GOSUB FindPlaceForO
  104. xo theRow, theColumn, 0: 'Places an O
  105. zO(theBox) = True: zE(theBox) = False
  106.  
  107. ComputeWin:
  108. IF WhoWon = 1 THEN
  109. IF XWin(1, 2, 3, 1) THEN RETURN
  110. IF XWin(4, 5, 6, 2) THEN RETURN
  111. IF XWin(7, 8, 9, 3) THEN RETURN
  112. IF XWin(1, 4, 7, 4) THEN RETURN
  113. IF XWin(2, 5, 8, 5) THEN RETURN
  114. IF XWin(3, 6, 9, 6) THEN RETURN
  115. IF XWin(1, 5, 9, 7) THEN RETURN
  116. IF XWin(3, 5, 7, 8) THEN RETURN
  117. IF OWin(1, 2, 3, 1) THEN RETURN
  118. IF OWin(4, 5, 6, 2) THEN RETURN
  119. IF OWin(7, 8, 9, 3) THEN RETURN
  120. IF OWin(1, 4, 7, 4) THEN RETURN
  121. IF OWin(2, 5, 8, 5) THEN RETURN
  122. IF OWin(3, 6, 9, 6) THEN RETURN
  123. IF OWin(1, 5, 9, 7) THEN RETURN
  124. IF OWin(3, 5, 7, 8) THEN RETURN
  125. WhoWon = 0
  126.  
  127. FindPlaceForO:
  128. ' See if there is a win for O. If so, take it.
  129. ' See if there is a threat of a win for X. If so, block it.
  130. FOR TestType% = 1 TO 2
  131. theBox = 0
  132. FOR theRow = 1 TO 3: FOR theColumn = 1 TO 3
  133. theBox = theBox + 1
  134. IF zE(theBox) THEN
  135. tk$ = ""
  136. SELECT CASE theBox
  137. CASE 1: tk$ = "234759"
  138. CASE 2: tk$ = "1358"
  139. CASE 3: tk$ = "126957"
  140. CASE 4: tk$ = "1756"
  141. CASE 5: tk$ = "19283746"
  142. CASE 6: tk$ = "4539"
  143. CASE 7: tk$ = "148935"
  144. CASE 8: tk$ = "2579"
  145. CASE 9: tk$ = "153678"
  146. FOR i = 1 TO LEN(tk$) STEP 2
  147. j = VAL(MID$(tk$, i, 1))
  148. k = VAL(MID$(tk$, i + 1, 1))
  149. IF TestType% = 1 THEN
  150. IF zO(j) + zO(k) < -1 THEN RETURN
  151. IF zX(j) + zX(k) < -1 THEN RETURN
  152. NEXT theColumn: NEXT theRow
  153. NEXT TestType%
  154. ' No move selected above to win or block win, so
  155. IF Hard THEN
  156. IF MovesMade = 1 THEN
  157. IF zE(5) THEN
  158. theRow = 2: theColumn = 2: theBox = 5
  159. IF RND > .5 THEN theRow = 1 ELSE theRow = 3
  160. IF RND > .5 THEN theColumn = 1 ELSE theColumn = 3
  161. theBox = (3 * (theRow - 1)) + theColumn
  162. ELSEIF MovesMade = 2 THEN
  163. IF zX(5) THEN
  164. tk$ = ""
  165. IF zO(1) AND zX(9) THEN
  166. tk$ = "37"
  167. ELSEIF zO(3) AND zX(7) THEN
  168. tk$ = "19"
  169. ELSEIF zO(7) AND zX(3) THEN
  170. tk$ = "19"
  171. ELSEIF zO(9) AND zX(1) THEN
  172. tk$ = "37"
  173. IF tk$ <> "" THEN
  174. IF RND > .5 THEN
  175. theBox = VAL(LEFT$(tk$, 1))
  176. theBox = VAL(LEFT$(tk$, 1))
  177. theRow = (theBox + 2) \ 3
  178. theColumn = theBox - (3 * (theRow - 1))
  179. DO: theBox = 2 * INT(1 + (RND * 4)): LOOP WHILE NOT zE(theBox)
  180. SELECT CASE theBox
  181. CASE 2: IF NOT zX(8) THEN EXIT DO
  182. CASE 4: IF NOT zX(6) THEN EXIT DO
  183. CASE 6: IF NOT zX(4) THEN EXIT DO
  184. CASE 8: IF NOT zX(2) THEN EXIT DO
  185. theRow = (theBox + 2) \ 3
  186. theColumn = theBox - (3 * (theRow - 1))
  187. ' OK, no good move was found. Make a random one
  188. DO: theBox = 1 + INT(RND * 9): LOOP WHILE NOT zE(theBox)
  189. theRow = (theBox + 2) \ 3
  190. theColumn = theBox - (3 * (theRow - 1))
  191.  
  192. Shuffle:
  193. DO WHILE LEN(w1$) < 4
  194. r% = 1 + INT(RND * 4)
  195. IF MID$(w2$, r%, 1) <> "x" THEN
  196. w1$ = w1$ + MID$(w2$, r%, 1)
  197. MID$(w2$, r%, 1) = "x"
  198.  
  199. ShowWhoWon:
  200. SELECT CASE WhoWon
  201. CASE 0: c$ = "Tie! "
  202. CASE 1: c$ = "YOU WIN! "
  203. CASE 2: c$ = "YOU LOSE! "
  204. CASE 3: c$ = "YOU RESIGNED?"
  205. IF WhoWon < 3 THEN SLEEP 2: WHILE INKEY$ <> "": WEND
  206. FOR i = 1 TO 30
  207. COLOR 1 + INT(RND * 15)
  208. LOCATE i, i + 20
  209. PRINT c$;
  210.  
  211. InitializeScreen:
  212. LOCATE 4, 23: PRINT "TIC TAC TOE by Paul Meyer & TheBOB"
  213. LOCATE 6, 27: PRINT "(C) 2004 - 2007 Dos-Id Games"
  214. ds% = 131: dd% = 97: dz% = 75
  215. LINE (ds%, 343)-(ds% + dz%, 380), , BF
  216. LINE (ds% + (1 * dd%), 343)-(ds% + (1 * dd%) + dz%, 380), , BF
  217. LINE (ds% + (2 * dd%), 343)-(ds% + (2 * dd%) + dz%, 380), , BF
  218. LINE (ds% + (3 * dd%), 343)-(ds% + (3 * dd%) + dz%, 380), , BF
  219. LOCATE 23, 19: PRINT " Easy ";
  220. LOCATE , 31: PRINT " Hard ";
  221. LOCATE , 43: PRINT " Info ";
  222. LOCATE , 55: PRINT " Quit "
  223.  
  224. FindClickedCommand:
  225. Command = 0
  226. CASE IS < 343: RETURN
  227. CASE IS > 380: RETURN
  228. CASE IS < 130: RETURN
  229. CASE IS < 205: Command = 1
  230. CASE IS < 227: RETURN
  231. CASE IS < 303: Command = 2
  232. CASE IS < 325: RETURN
  233. CASE IS < 400: Command = 3
  234. CASE IS < 421: RETURN
  235. CASE IS < 497: Command = 4
  236.  
  237.  
  238. DoHelp:
  239. LOCATE 3, 1
  240. PRINT "Credits"
  241. PRINT "-------"
  242. PRINT "This game was created by Paul Meyer in the year 2007."
  243. PRINT : PRINT "Graphics by TheBob"
  244. PRINT : PRINT "Improved mouse driver, modularity, machine play-to-win";
  245. PRINT " by QBasic Mac"
  246. PRINT : PRINT "History:"
  247. PRINT "http://www.network54.com/Forum/190883/message/1175106480"
  248. PRINT "This is freeware, you may change this as much as you want"
  249. PRINT "as long as you don't claim it as yours."
  250. PRINT "About"
  251. PRINT "-----"
  252. PRINT "This is just a simple TIC TAC TOE game with mouse drivers."
  253. PRINT "This game was created in QuickBasic."
  254. CALL GetUserSignal
  255.  
  256. SUB DrawSCREEN
  257. STATIC Finished AS INTEGER
  258. OUT &H3C8, 0: OUT &H3C9, 0: OUT &H3C9, 0: OUT &H3C9, 18
  259. OUT &H3C8, 4: OUT &H3C9, 63: OUT &H3C9, 0: OUT &H3C9, 0
  260. OUT &H3C8, 9: OUT &H3C9, 0: OUT &H3C9, 12: OUT &H3C9, 48
  261. OUT &H3C8, 11: OUT &H3C9, 0: OUT &H3C9, 18: OUT &H3C9, 54
  262. COLOR 7: LOCATE 3, 31: PRINT "T I C - T A C - T O E"
  263. LINE (170, 90)-(490, 410), 0, BF
  264. LINE (160, 81)-(479, 399), 1, BF
  265. LINE (155, 76)-(483, 404), 8, B
  266. LINE (152, 73)-(487, 407), 8, B
  267. LINE (160, 81)-(160, 399), 9
  268. LINE (160, 81)-(479, 81), 9
  269. LINE (371, 92)-(372, 393), 0, B
  270. LINE (271, 92)-(272, 392), 0, B
  271. LINE (171, 191)-(472, 192), 0, B
  272. LINE (171, 291)-(472, 292), 0, B
  273. LINE (369, 90)-(370, 390), 13, B
  274. LINE (269, 90)-(270, 390), 13, B
  275. LINE (169, 189)-(470, 190), 13, B
  276. LINE (169, 289)-(470, 290), 13, B
  277. LINE (5, 5)-(634, 474), 8, B
  278. LINE (10, 10)-(629, 469), 8, B
  279. IF Finished THEN EXIT SUB
  280. Finished = True
  281. FOR x = 194 TO 500
  282. FOR y = 32 TO 46
  283. IF POINT(x, y) = 8 THEN PSET (x, y), 7
  284. PSET (188, 108), 0
  285. DRAW "E3 F30 E30 F6 G30 F30 G6 H30 G30 H6 E30 H30 E3 BF2 P0,0"
  286. PSET (186, 106), 10
  287. DRAW "E3 F30 E30 F6 G30 F30 G6 H30 G30 H6 E30 H30 E3 BF2 P10,10"
  288. CIRCLE (322, 141), 31, 0
  289. CIRCLE (322, 141), 37, 0
  290. PAINT STEP(0, 35), 0
  291. PSET STEP(0, -35), 0
  292. CIRCLE (320, 139), 31, 4
  293. CIRCLE (320, 139), 37, 4
  294. PAINT STEP(0, 35), 4
  295. PSET STEP(0, -35), 1
  296. GET STEP(-40, -40)-STEP(81, 81), SymbolBOX
  297. GET (179, 98)-(260, 178), SymbolBOX(3000)
  298. xo 1, 1, 2: xo 1, 2, 2
  299.  
  300. SUB EnableMouse (c%)
  301. IF Status = 0 AND c% = 0 THEN EXIT SUB
  302. IF Mx = "" THEN
  303. m$ = "58E85080585080585080850815510C358508058508085080850815C00"
  304. n$ = "595BECB70BEAB70BE8BFBE6B7B8E7D33BEC978BEA97BE89FBE697DA80"
  305. Mx = SPACE$(57)
  306. FOR i% = 1 TO 57
  307. H$ = CHR$(VAL("&H" + MID$(m$, i%, 1) + MID$(n$, i%, 1)))
  308. MID$(Mx, i%, 1) = H$
  309. NEXT i%
  310. IF c% = 0 THEN
  311. CALL Absolute(2, click, cH, cV, SADD(Mx))
  312. Status = 0
  313. IF Status = 0 THEN CALL Absolute(1, click, cH, cV, SADD(Mx))
  314. Status = 1
  315. CALL Absolute(3, click, cH, cV, SADD(Mx))
  316.  
  317. SUB GetUserSignal
  318. IF 0 THEN ' Set to 1 for Debugging printout, otherwise 0
  319. LOCATE 2, 1
  320. PRINT click; "<Click"
  321. PRINT cH; "ch (Horizontal)"
  322. PRINT cV; "cv (Verticle)"
  323. EnableMouse 1
  324. IF click > 0 THEN
  325. k% = click
  326. WHILE click <> 0: EnableMouse 1: WEND
  327. click = k%
  328. cC = INKEY$
  329. LOOP WHILE cC = ""
  330. EnableMouse 0
  331.  
  332. FUNCTION OWin% (b1 AS INTEGER, b2 AS INTEGER, b3 AS INTEGER, l AS INTEGER)
  333. IF zO(b1) = 0 OR zO(b2) = 0 OR zO(b3) = 0 THEN EXIT FUNCTION
  334. Winner l
  335. OWin% = -1
  336.  
  337. SUB Winner (Lineup AS INTEGER)
  338. SELECT CASE Lineup
  339. CASE 1: LINE (200, 140)-(440, 142), 14, BF: LINE (200, 143)-(440, 144), 0, B
  340. CASE 2: LINE (200, 240)-(440, 242), 14, BF: LINE (200, 243)-(440, 244), 0, B
  341. CASE 3: LINE (200, 340)-(440, 342), 14, BF: LINE (200, 343)-(440, 344), 0, B
  342. CASE 4: LINE (220, 120)-(222, 360), 14, BF: LINE (223, 120)-(223, 360), 0
  343. CASE 5: LINE (320, 120)-(322, 360), 14, BF: LINE (323, 120)-(323, 360), 0
  344. CASE 6: LINE (420, 120)-(422, 360), 14, BF: LINE (423, 120)-(423, 360), 0
  345. CASE 7: PSET (200, 120), 14: DRAW "F240 d H240 d F240 d H240 d C0 F240 d H240"
  346. CASE 8: PSET (440, 120), 14: DRAW "G240 d E240 d G240 d E240 d C0 G240 d E240"
  347.  
  348. SUB xo (Row AS INTEGER, Col AS INTEGER, symbol AS INTEGER)
  349. x = (Col - 1) * 100 + 180
  350. y = (Row - 1) * 100 + 100
  351. Index = symbol * 3000
  352. IF Index < 6000 THEN
  353. PUT (x, y), SymbolBOX(Index), PSET
  354. LINE (x, y)-(x + 80, y + 80), 1, BF
  355.  
  356. FUNCTION XWin% (b1 AS INTEGER, b2 AS INTEGER, b3 AS INTEGER, l AS INTEGER)
  357. IF zX(b1) = 0 OR zX(b2) = 0 OR zX(b3) = 0 THEN EXIT FUNCTION
  358. Winner l
  359. XWin% = -1
Title: Re: QBasic OS
Post by: TempodiBasic on March 26, 2020, 05:19:49 pm
Hi Eric
it seems TicTacToe.BAS a Bob Seguin's product for graphics that travels in the sample package of QB64.

PS It has a bug that I fixed... :-)
Title: Re: QBasic OS
Post by: EricE on March 26, 2020, 05:55:04 pm
Hi TempodiBasic,
I found the code by using Google to search for various substrings of this comment string.
"This game was created by Paul Meyer in the year 2007."
I will look for the fixed sample version.

EDIT
And I found it! We all had the improved, fixed version ready for us to use.

C:\qb64_1.4_win-x86\qb64\programs\samples\n54\big\tictac.bas
Title: Re: QBasic OS
Post by: TempodiBasic on March 26, 2020, 06:53:48 pm
Hi Eric
this version that is in the sample package of QB64  has the interface written by Bob Seguin as you can read also if you run it.
Good let run it and then please choose Hard, then as first player make as choice the rightest square (cell) of the middle raw, the AI will respond taking the center with O,  now make as choice the center square of the bottom raw...! You got it! a runtime error for Subscript out of range!
Searching on the [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] you'll find my fix to this.
Or You'll be able to fix following the flow of the program.
Title: Re: QBasic OS
Post by: EricE on March 26, 2020, 09:06:49 pm
Quote
Searching on the [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] you'll find my fix to this

I am sorry to say that I could not find your fix at [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there].

[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] is not complete, there are many links there that just lead back to its main page.
Title: Re: QBasic OS
Post by: qbkiller101 on March 27, 2020, 04:17:27 am
Quote
Is this the code
yeah
Title: Re: QBasic OS
Post by: TempodiBasic on March 29, 2020, 04:34:23 pm
Hey Guys
on an old Notebook I have found my fix to TicTacToe
here is
as attachment
Title: Re: QBasic OS
Post by: EricE on March 29, 2020, 08:21:33 pm
Thank you TempodiBasic,
However, the attachment you uploaded is damaged.
Did it open ok before you uploaded it?
Title: Re: QBasic OS
Post by: qbkiller101 on March 30, 2020, 05:27:35 am
I guess he sort of opened the .exe in qb64 or something cuz that's what happens when you open .exe in text editors or compilers
Title: Re: QBasic OS
Post by: TempodiBasic on March 30, 2020, 07:18:11 am
Hi Eric
sorry that is a QB compressed file

here the text version...
Code: QB64: [Select]
  1. DECLARE SUB Winner (Lineup AS INTEGER)
  2. DECLARE SUB ShowWin (b1 AS INTEGER, b2 AS INTEGER, b3 AS INTEGER)
  3. DECLARE SUB GetUserSignal ()
  4. DECLARE SUB EnableMouse (c%)
  5. DECLARE SUB DrawSCREEN ()
  6. DECLARE SUB xo (Row%, Col%, symbol%)
  7.  
  8. DIM SHARED False AS INTEGER, True AS INTEGER: True = NOT False
  9. DIM SHARED SymbolBOX(6000) AS INTEGER '<---NOTE
  10.  
  11. DIM SHARED cH AS INTEGER: 'Cursor Position Horizontal
  12. DIM SHARED cV AS INTEGER: 'Cursor Position Vertical
  13. DIM SHARED click AS INTEGER: ' 0=no click, 1=left click, 2=right
  14. ' EnableMouse 1 = Turn cursor on, return coordinates
  15. ' EnableMouse 0 = Turn cursor off in order to draw stuff, etc.
  16. DIM SHARED cC AS STRING: 'User pressed key
  17. ' GetUserSignal will set return cC or will return Click
  18.  
  19. DIM WhoWon AS INTEGER
  20. DIM MadeAMove AS INTEGER, MovesMade AS INTEGER
  21.  
  22. ' ----------------------------------------------------------
  23. ' Title Screen (Main Program)
  24. ' -----------------------------------------------------------
  25. SCREEN 12 ' modalita schermo / screen mode
  26. RANDOMIZE TIMER ' inizializza generatore di numeri casuali / it inizializes maker of random numbers
  27. DIM Command AS INTEGER, Hard AS INTEGER
  28. ' variabili generali non visibili in SUB per cui usa GOSUB
  29. ' general variables non seen in SUB so He uses GOSUB
  30. GOSUB InitializeScreen ' schermo iniziale con pulsanti / initial screen with buttons
  31.  
  32. DO ' ciclo principale infinito / main loop infinite
  33.     DO: GetUserSignal: LOOP UNTIL click = 1 ' attende il click/ it waits for click
  34.     GOSUB FindClickedCommand ' decodifica il click / it decodes click
  35.     SELECT CASE Command
  36.         CASE 1: ' primo pulsante / first button
  37.             Hard = False
  38.             WhoWon = 0
  39.             GOSUB PlayGame
  40.             GOSUB ShowWhoWon
  41.             GOSUB InitializeScreen
  42.         CASE 2: ' secondo pulsante / second button
  43.             Hard = True
  44.             WhoWon = 0
  45.             GOSUB PlayGame
  46.             GOSUB ShowWhoWon
  47.             GOSUB InitializeScreen
  48.         CASE 3: ' terzo pulsante /third button
  49.             GOSUB DoHelp
  50.             GOSUB InitializeScreen
  51.         CASE 4: 'forth button / quarto pulsante
  52.             EXIT DO ' esce dal ciclo/ it exits from loop
  53.     END SELECT
  54. COLOR 7: CLS ' ripristina i caratteri bianchi e pulisce lo schermo/ it restores white character and clear screen
  55. SYSTEM ' termina liberando le risorse / it stops releasing resources
  56.  
  57. ' ----------------------------------------------------------
  58. ' Game Screen
  59. ' -----------------------------------------------------------
  60. DIM SHARED zX(9) AS INTEGER: ' Where all X's are placed
  61. DIM SHARED zO(9) AS INTEGER: ' Where all O's are placed
  62. DIM SHARED zE(9) AS INTEGER: ' Where empty squares are
  63. DIM theRow AS INTEGER, theColumn AS INTEGER, theBox AS INTEGER
  64.  
  65. FindClickedPosition: ' cerca la posizione del mouse/ it finds position of mouse
  66. CONST Delta = 4
  67. theRow = 0: theColumn = 0: theBox = 0
  68. SELECT CASE cH ' posizione orizzontale / horizontal position
  69.     CASE IS < 170 + Delta: RETURN
  70.     CASE IS < 269 - Delta: theColumn = 1 ' tra 174 e 265 colonna 1 / between 174 and 265 column 1
  71.     CASE IS < 269 + Delta: RETURN
  72.     CASE IS < 368 - Delta: theColumn = 2 ' tra 274 e 364 colonna 2 / between 274 and 364 column 2
  73.     CASE IS < 368 + Delta: RETURN
  74.     CASE IS < 467 - Delta: theColumn = 3 ' tra 372 e 463 colonna 3/ between 372 and 463 column 3
  75. SELECT CASE cV ' posizione verticale / vertical position
  76.     CASE IS < 91 + Delta: RETURN
  77.     CASE IS < 190 - Delta: theRow = 1 ' tra 95 e 186 riga 1/ between 95 and 186 row 1
  78.     CASE IS < 190 + Delta: RETURN
  79.     CASE IS < 289 - Delta: theRow = 2 'tra 194 e 285 riga 2/between 194 3 285 row 2
  80.     CASE IS < 289 + Delta: RETURN
  81.     CASE IS < 388 - Delta: theRow = 3 ' tra 294 e 384 riga 3 / between 294 e 384 row 3
  82. theBox = (3 * (theRow - 1)) + theColumn ' calcola la cella/ it calculates cell
  83. ' nota che si possono invertire TheRow e TheColumn nella formula
  84. ' see that it can invert TheRow and TheColumn in formula
  85.  
  86. ' ----------------------------------------------------------
  87. ' Play Game
  88. ' -----------------------------------------------------------
  89. PlayGame: ' schermata di gioco / screen of game
  90. DrawSCREEN 'draw the screen and create X and O symbols.
  91. FOR i = 1 TO 9: zO(i) = False: zX(i) = False: zE(i) = True: NEXT i
  92. ' inizializza i 3 arrays Empty a vero X e 0 a falso
  93. ' it inizializes the three arrays Empty to true   X and 0 to false
  94. MovesMade = 0 ' mosse fatte = 0 / moves made = 0
  95.     GetUserSignal 'aspetta azione utente/ it waits action of user
  96.     IF click THEN
  97.         MadeAMove = False ' flag fatta una mossa / flag made a move
  98.         GOSUB MakeX ' fa la X       / if it maked X
  99.         IF MadeAMove THEN ' se Š fatta la mossa    / if it made a move
  100.             WhoWon = 1: GOSUB ComputeWin: IF WhoWon = 1 THEN RETURN
  101.             'WhoWon flag per cercare il vincitore / WhoWon is flag to seek for winner
  102.             t% = 0
  103.             FOR i = 1 TO 9: t% = t% + zX(i): NEXT i
  104.             IF t% = -5 THEN WhoWon = 0: RETURN
  105.             ' se ci sono 5 X allora ci saranno 4 0 e sar… pari
  106.             ' if there is 5 X then there shoude be 4 0s and it is tie
  107.             MovesMade = MovesMade + 1 ' conta mosse/ it counts moves
  108.             GOSUB MakeO
  109.             WhoWon = 2: GOSUB ComputeWin: IF WhoWon = 2 THEN RETURN
  110.             'WhoWon flag per cercare il vincitore / WhoWon is flag to seek for winner
  111.         END IF
  112.     END IF
  113.     IF cC = "d" OR cC = CHR$(27) THEN WhoWon = 3 ' utente vuole uscire / users wants to exit
  114.     IF WhoWon > 0 THEN RETURN ' se qualcuno vince ritorna al ciclo principale / if someone wins it returns to main loop
  115.  
  116. MakeX:
  117. GOSUB FindClickedPosition ' decodifica il click/ it decodes click
  118. IF theBox = 0 THEN RETURN ' esce se non ha scelto / t exits if it doesn't choose
  119. IF NOT zE(theBox) THEN RETURN ' esce se la cella non Š vuota/ it exits if cell is not void
  120. xo theRow, theColumn, 1: ' Places an X
  121. zX(theBox) = True: zE(theBox) = False ' aggiorna array X e Empty / it refreshes arrays X and Empty
  122. MadeAMove = True ' flag fatta la mossa
  123.  
  124. MakeO:
  125. GOSUB FindPlaceForO ' modulo IA per 0/ modulo AI for 0
  126. SLEEP 1: WHILE INKEY$ <> "": WEND ' aspetta 1 secondo/ it waits for 1 second
  127. xo theRow, theColumn, 0: 'Places an 0  /mette uno 0
  128. zO(theBox) = True: zE(theBox) = False ' imposta gli array / it sets arrays
  129.  
  130. ComputeWin: ' PC usando 0 vince / PC using 0 wins
  131. IF WhoWon = 1 THEN ' calcola se ha vinto la X/ it calculates if X wins
  132.     IF XWin(1, 2, 3, 1) THEN RETURN
  133.     IF XWin(4, 5, 6, 2) THEN RETURN
  134.     IF XWin(7, 8, 9, 3) THEN RETURN
  135.     IF XWin(1, 4, 7, 4) THEN RETURN
  136.     IF XWin(2, 5, 8, 5) THEN RETURN
  137.     IF XWin(3, 6, 9, 6) THEN RETURN
  138.     IF XWin(1, 5, 9, 7) THEN RETURN
  139.     IF XWin(3, 5, 7, 8) THEN RETURN
  140. ELSE ' calcola se ha vinto lo 0/ it calculates if 0 wins
  141.     IF OWin(1, 2, 3, 1) THEN RETURN
  142.     IF OWin(4, 5, 6, 2) THEN RETURN
  143.     IF OWin(7, 8, 9, 3) THEN RETURN
  144.     IF OWin(1, 4, 7, 4) THEN RETURN
  145.     IF OWin(2, 5, 8, 5) THEN RETURN
  146.     IF OWin(3, 6, 9, 6) THEN RETURN
  147.     IF OWin(1, 5, 9, 7) THEN RETURN
  148.     IF OWin(3, 5, 7, 8) THEN RETURN
  149. WhoWon = 0 ' nessuno vince/ nobody wins
  150.  
  151. FindPlaceForO: ' qui c'Š il problema ovvero opera incompiuta / here is problem otherwise work unfinished
  152. ' See if there is a win for O. If so, take it.
  153. ' See if there is a threat of a win for X. If so, block it.
  154. ' cerca se c'Š  una posizione che fa vincere 0 in tal caso la sceglie
  155. ' cerca se c'Š una posizione che fa vincere X in tal caso le blocca
  156. FOR TestType% = 1 TO 2
  157.     theBox = 0 ' nessuna cella scelta /no cell choosen
  158.     FOR theRow = 1 TO 3: FOR theColumn = 1 TO 3
  159.             ' per tutte le righe e per tutte le colonne
  160.             ' for all rows and all columns
  161.             theBox = theBox + 1 ' aumenta il numero di cella /it increases number of cell
  162.             IF zE(theBox) THEN ' se Š vuota / if it is void
  163.                 tk$ = ""
  164.                 SELECT CASE theBox ' sceglie le celle da controllare/ it chooses cells to control
  165.                     CASE 1: tk$ = "234759"
  166.                     CASE 2: tk$ = "1358"
  167.                     CASE 3: tk$ = "126957"
  168.                     CASE 4: tk$ = "1756"
  169.                     CASE 5: tk$ = "19283746"
  170.                     CASE 6: tk$ = "4539"
  171.                     CASE 7: tk$ = "148935"
  172.                     CASE 8: tk$ = "2579"
  173.                     CASE 9: tk$ = "153678"
  174.                 END SELECT
  175.                 ' controlla le celle / it controls cells
  176.                 FOR i = 1 TO LEN(tk$) STEP 2
  177.                     j = VAL(MID$(tk$, i, 1))
  178.                     k = VAL(MID$(tk$, i + 1, 1))
  179.                     ' prende due celle successive / it takes two cells successive
  180.                     IF TestType% = 1 THEN
  181.                         ' cerca 2 celle con 0 se si, fa  tris / it seeks for 2 cells with 0 if yes it will make tris
  182.                         IF zO(j) + zO(k) < -1 THEN RETURN
  183.                     ELSE
  184.                         ' cerca 2 celle con X se si blocca il tris di X / it searches 2 cells with X if yes it will block tris of X
  185.                         IF zX(j) + zX(k) < -1 THEN RETURN
  186.                     END IF
  187.                 NEXT i
  188.             END IF
  189.     NEXT theColumn: NEXT theRow
  190. NEXT TestType%
  191. ' No move selected above to win or block win, so  / nessuna mossa per vincere o bloccare X quindi
  192. IF Hard THEN ' modalit… difficile / hard mode
  193.     IF MovesMade = 1 THEN ' fatta una sola mossa/ it has made one move
  194.         IF zE(5) THEN ' se la cella centrale Š vuota la prende/ if central cell is empty it takes
  195.             theRow = 2: theColumn = 2: theBox = 5
  196.         ELSE
  197.             IF RND > .5 THEN theRow = 1 ELSE theRow = 3 ' sceglie a caso riga superiore o inferiore/ it chooses at random upper row or lower row
  198.             IF RND > .5 THEN theColumn = 1 ELSE theColumn = 3 ' sceglia a caso colonna 1 o 3/ it choosed at random column 1 or 3
  199.             theBox = (3 * (theRow - 1)) + theColumn ' calcola uno degli angoli della griglia/ it calculates one of angles of grid
  200.             ' anche qui TheRow e TheColumn sono intercambiabili
  201.             ' also here TheRow e TheColumn are interchangeable
  202.         END IF
  203.         RETURN
  204.     ELSEIF MovesMade = 2 THEN 'se X ha fatto 2 mosse / se X has made two moves
  205.         IF zX(5) THEN ' se X sta al centro  / if X is at centre cell
  206.             'se due angoli sono presi esamina gli altri due
  207.             ' if 2 angles are taken it examines the other two  angles
  208.             tk$ = ""
  209.             IF zO(1) AND zX(9) THEN ' se angoli 1 e 9 sono presi/ if angles 1 and 9 are taken
  210.                 tk$ = "37"
  211.             ELSEIF zO(3) AND zX(7) THEN ' se angoli 3 e 7 sono presi/ if angles 3 and 7 are taken
  212.                 tk$ = "19"
  213.             ELSEIF zO(7) AND zX(3) THEN ' se angoli 3 e 7 sono presi/ if angles 3 and 7 are taken
  214.                 tk$ = "19"
  215.             ELSEIF zO(9) AND zX(1) THEN ' se angoli 1 e 9 sono presi/ if angles 1 and 9 are taken
  216.                 tk$ = "37"
  217.             END IF
  218.             IF tk$ <> "" THEN 'se ci sono celle da esaminare/ if there are cells to examine
  219.                 IF RND > .5 THEN
  220.                     theBox = VAL(LEFT$(tk$, 1))
  221.                 ELSE
  222.                     theBox = VAL(LEFT$(tk$, 1))
  223.                 END IF
  224.                 ' sceglie a caso tra la prima cella della riga e la prima cella della riga???
  225.                 'forse ci vuole RIGHT$ nell'ELSE
  226.                 ' it chooses at random between first cell of row and first cell of row! ! ??
  227.                 ' maybe here is right RIGHT$ in ELSE
  228.  
  229.                 theRow = (theBox + 2) \ 3 ' ottiene come risultato 1 o 3 / it gets as results 1 or 3
  230.                 theColumn = theBox - (3 * (theRow - 1)) ' ottiene come risultato 1 o 3/ it gets as results 1 or 3
  231.                 ' le celle da scegliere sono 1 (1,1) 3 (1,3) 7(3,1) 9(3,3) Cella(TheRow,TheColumn)
  232.                 ' the  cells to choose are 1(1,1) 3 (1,3) 7 (3,1) 9 (3,3)  Cell(TheRow,TheColumn)
  233.                 RETURN
  234.             END IF
  235.         ELSE
  236.             'se la X non sta al centro / if X is not at centre
  237.             escape% = 0 ' variabile per uscire dal loop infinito / variable to exit from infinite loop
  238.             DO
  239.                 DO:
  240.                     theBox = 2 * FIX(1 + (RND * 4)):
  241.                     ' genera a caso un numero da 1 a 10  /it makes a rnd_number from 1 to 10
  242.                     ' il 10 capita all'incirca ogni 20 secondi e crea un errore in zE(TheBox)/ the 10 arrives about each 20 seconds and it makes error in zE(TheBox)
  243.                     'cos ci vuole un controllo forte ad esempio un if TheBox = 10 then TheBox = MaxPossibleNotAngle (8)/so it need a strong control for example if TheBox = 10 then TheBox = MaxPossibleNotAngle (8)
  244.  
  245.                     ' codice di verifica/ degub code
  246.                     ' LOCATE 28, 2: PRINT "theBox "; theBox, "zE(theBox) "; zE(theBox), "NOT zE(theBox) "; NOT zE(theBox)
  247.  
  248.                 LOOP WHILE NOT zE(theBox)
  249.                 SELECT CASE theBox
  250.                     CASE 2: IF NOT zX(8) THEN EXIT DO ELSE escape% = escape% + 1 'prende la casella 2 se la casella 8 Š  vuota/ it chooses cell 2 if cell 8 is empty
  251.                     CASE 4: IF NOT zX(6) THEN EXIT DO ELSE escape% = escape% + 1 'prende la casella 4 se la casella 6 Š  vuota/ it chooses cell 4 if cell 6 is empty
  252.                     CASE 6: IF NOT zX(4) THEN EXIT DO ELSE escape% = escape% + 1 'prende la casella 6 se la casella 4 Š  vuota/ it chooses cell 6 if cell 4 is empty
  253.                     CASE 8: IF NOT zX(2) THEN EXIT DO ELSE escape% = escape% + 1 'prende la casella 8 se la casella 2 Š  vuota/ it chooses cell 8 if cell 2 is empty
  254.                 END SELECT
  255.                 ' 1 perchŠ non sceglie un angolo? / why doesn't it choose an angle?
  256.                 '2 cosa fa se la casella opposta Š occupata?/ what does it, if the opposite cell is plenty?
  257.                 ' qui manca del codice per uscire dal loop/ here there is no code to exit loop
  258.                 IF (zX(2) AND zX(4) AND zO(5) AND zE(1)) THEN theBox = 1
  259.                 IF (zX(2) AND zX(6) AND zO(5) AND zE(3)) THEN theBox = 3
  260.                 IF (zX(4) AND zX(8) AND zO(5) AND zE(7)) THEN theBox = 7
  261.                 IF (zX(6) AND zX(8) AND zO(5) AND zE(9)) THEN theBox = 9
  262.  
  263.             LOOP UNTIL (((theBox + 1) MOD 2) OR escape% = 16) '4 * 4 = 16 , in 16 loop tester… almeno una volta le 4 condizioni/ 4*4 = 16 in 16 loops it will test at least a time each of 4 conditions
  264.             theRow = (theBox + 2) \ 3 ' calcola 1,2,2,3 rispettivamente a 2,4,6,8/ it calculates 1,2,2,3 for respectively 2,4,6,8
  265.             theColumn = theBox - (3 * (theRow - 1)) ' calcola 2,1,3,2 seguendo i valori superiori/ it calculates 2,1,3,2 following the above values
  266.             RETURN
  267.         END IF
  268.     END IF
  269. ' OK, no good move was found. Make a random one
  270. ' nessuna buona mossa da fare ne fa una a caso
  271. DO: theBox = 1 + INT(RND * 9): LOOP WHILE NOT zE(theBox)
  272. theRow = (theBox + 2) \ 3
  273. theColumn = theBox - (3 * (theRow - 1))
  274.  
  275. Shuffle:
  276. DO WHILE LEN(w1$) < 4
  277.     r% = 1 + INT(RND * 4)
  278.     IF MID$(w2$, r%, 1) <> "x" THEN
  279.         w1$ = w1$ + MID$(w2$, r%, 1)
  280.         MID$(w2$, r%, 1) = "x"
  281.     END IF
  282.  
  283. ShowWhoWon: ' mostra vincitore/ it shows winner
  284. SELECT CASE WhoWon ' 4 casi Pari , Vinci, Perdi, Abbandoni / 4 cases Tie, win, lose, resigne
  285.     CASE 0: c$ = "Tie! "
  286.     CASE 1: c$ = "YOU WIN! "
  287.     CASE 2: c$ = "YOU LOSE! "
  288.     CASE 3: c$ = "YOU RESIGNED?"
  289. IF WhoWon < 3 THEN SLEEP 2: WHILE INKEY$ <> "": WEND ' se non abbandona aspetta un tasto /if it doesn't resign , it waits a key
  290. FOR i = 1 TO 30
  291.     COLOR 1 + INT(RND * 15)
  292.     LOCATE i, i + 20
  293.     PRINT c$;
  294. SLEEP 3: WHILE INKEY$ <> "": WEND ' aspetta almeno 3 secondi/ it waits at least 3 seconds
  295.  
  296. InitializeScreen: ' crea la schermata iniziale del gioco / it creates initial screen game
  297. LOCATE 4, 23: PRINT "TIC TAC TOE by Paul Meyer & TheBOB"
  298. LOCATE 7, 27: PRINT "(C) 2004 - 2007 Dos-Id Games"
  299. LOCATE 5, 23: PRINT "Debugged and improved IA by TempodiBasic"
  300. ds% = 131: dd% = 97: dz% = 75 ' i 4 pulsanti / 4 buttons
  301. LINE (ds%, 343)-(ds% + dz%, 380), , BF
  302. LINE (ds% + (1 * dd%), 343)-(ds% + (1 * dd%) + dz%, 380), , BF
  303. LINE (ds% + (2 * dd%), 343)-(ds% + (2 * dd%) + dz%, 380), , BF
  304. LINE (ds% + (3 * dd%), 343)-(ds% + (3 * dd%) + dz%, 380), , BF
  305. LOCATE 23, 19: PRINT " Easy "; ' 4 comandi per pulsanti / 4 command for buttons
  306. LOCATE , 31: PRINT " Hard ";
  307. LOCATE , 43: PRINT " Info ";
  308. LOCATE , 55: PRINT " Quit "
  309.  
  310. FindClickedCommand: ' da un significato al click / it gives a signify to click
  311. Command = 0
  312. SELECT CASE cV ' click in posizione verticale fuori oggetti / click in vertical position out of objects
  313.     CASE IS < 343: RETURN
  314.     CASE IS > 380: RETURN
  315. SELECT CASE cH ' click in posizione orizzontale / click in horizontal position
  316.     CASE IS < 130: RETURN ' area vuota / void area
  317.     CASE IS < 205: Command = 1 ' tra 130 e 204 /between 130 and 204
  318.     CASE IS < 227: RETURN ' area vuota / void area
  319.     CASE IS < 303: Command = 2 'tra 227 e 302 / between 227 e 302
  320.     CASE IS < 325: RETURN ' area vuota / void area
  321.     CASE IS < 400: Command = 3 ' tra 325 e 399/ between 325 e 399
  322.     CASE IS < 421: RETURN ' area vuota / void area
  323.     CASE IS < 497: Command = 4 ' tra 421 e 496/ between 421 and 496
  324.  
  325.  
  326. DoHelp: ' subroutine vecchio stile con gosub_return/ soubroutine old style by gosub_return
  327. ' mostra info / it shows info
  328. LOCATE 3, 1
  329. PRINT "Credits"
  330. PRINT "-------"
  331. PRINT "This game was created by Paul Meyer in the year 2007."
  332. PRINT: PRINT "Graphics by TheBob"
  333. PRINT: PRINT "Improved mouse driver, modularity, machine play-to-win";
  334. PRINT " by QBasic Mac"
  335. PRINT " Debugging and improve IA by TempodiBasic"
  336. PRINT: PRINT "History:"
  337. PRINT "http://www.network54.com/Forum/190883/message/1175106480"
  338. PRINT "following QB64 package for years, debugged in 09 07 2016"
  339. PRINT "This is freeware, you may change this as much as you want"
  340. PRINT "as long as you don't claim it as yours."
  341. PRINT "About"
  342. PRINT "-----"
  343. PRINT "This is just a simple TIC TAC TOE game with mouse drivers."
  344. PRINT "This game was created in QuickBasic."
  345. CALL GetUserSignal 'aspetta un click o tasto premuto /it waits for a click o key_pressed
  346.  
  347. SUB DrawSCREEN ' crea schermata gioco / it draws screen of game
  348. STATIC Finished AS INTEGER
  349. ' scrive direttamente codice esadecimale alla RAM video
  350. ' it writes directly Hex code into RAM of video
  351. OUT &H3C8, 0: OUT &H3C9, 0: OUT &H3C9, 0: OUT &H3C9, 18
  352. OUT &H3C8, 4: OUT &H3C9, 63: OUT &H3C9, 0: OUT &H3C9, 0
  353. OUT &H3C8, 9: OUT &H3C9, 0: OUT &H3C9, 12: OUT &H3C9, 48
  354. OUT &H3C8, 11: OUT &H3C9, 0: OUT &H3C9, 18: OUT &H3C9, 54
  355. COLOR 7: LOCATE 3, 31: PRINT "T I C - T A C - T O E"
  356. LINE (170, 90)-(490, 410), 0, BF
  357. LINE (160, 81)-(479, 399), 1, BF
  358. LINE (155, 76)-(483, 404), 8, B
  359. LINE (152, 73)-(487, 407), 8, B
  360. LINE (160, 81)-(160, 399), 9
  361. LINE (160, 81)-(479, 81), 9
  362. LINE (371, 92)-(372, 393), 0, B
  363. LINE (271, 92)-(272, 392), 0, B
  364. LINE (171, 191)-(472, 192), 0, B
  365. LINE (171, 291)-(472, 292), 0, B
  366. LINE (369, 90)-(370, 390), 13, B
  367. LINE (269, 90)-(270, 390), 13, B
  368. LINE (169, 189)-(470, 190), 13, B
  369. LINE (169, 289)-(470, 290), 13, B
  370. LINE (5, 5)-(634, 474), 8, B
  371. LINE (10, 10)-(629, 469), 8, B
  372. IF Finished THEN EXIT SUB
  373. Finished = True ' la prima volta imposta finished = vero  / first time it sets finished = true
  374. ' e poi genera i simboli 0 e X e li mette in array per immagini alle posizioni 0 e 3000
  375. ' and the it makes symbols 0 and X and it puts them in array for images at positions 0 and 3000
  376. FOR x = 194 TO 500
  377.     FOR y = 32 TO 46
  378.         IF POINT(x, y) = 8 THEN PSET (x, y), 7
  379.     NEXT y
  380. PSET (188, 108), 0
  381. DRAW "E3 F30 E30 F6 G30 F30 G6 H30 G30 H6 E30 H30 E3 BF2 P0,0"
  382. PSET (186, 106), 10
  383. DRAW "E3 F30 E30 F6 G30 F30 G6 H30 G30 H6 E30 H30 E3 BF2 P10,10"
  384. CIRCLE (322, 141), 31, 0
  385. CIRCLE (322, 141), 37, 0
  386. PAINT STEP(0, 35), 0
  387. PSET STEP(0, -35), 0
  388. CIRCLE (320, 139), 31, 4
  389. CIRCLE (320, 139), 37, 4
  390. PAINT STEP(0, 35), 4
  391. PSET STEP(0, -35), 1
  392. GET STEP(-40, -40)-STEP(81, 81), SymbolBOX() ' mette 0 in posizione 0 / it puts 0 in position 0
  393. GET (179, 98)-(260, 178), SymbolBOX(3000) 'mette X in posizione 3000 / it puts X in position 3000
  394. xo 1, 1, 2: xo 1, 2, 2 ' cancella i simboli dalle celle / it cancels symbols from cells
  395.  
  396. SUB EnableMouse (c%)
  397. STATIC Status AS INTEGER ' variabile conservata / variable stored
  398. ' status indica lo stato del mouse 0 spento 1 acceso       / status shows 0 mouse off 1 mouse on
  399. ' c% Š la funzione da eseguire 0 spegnere 1 accendere 3 rilevare/ C% is function to act 0 turn off 3 detect
  400. IF Status = 0 AND c% = 0 THEN EXIT SUB
  401. STATIC Mx AS STRING 'variabile conservata/ variable stored
  402. IF Mx = "" THEN 'inizializza Mx / it inizializes Mx
  403.     m$ = "58E85080585080585080850815510C358508058508085080850815C00"
  404.     n$ = "595BECB70BEAB70BE8BFBE6B7B8E7D33BEC978BEA97BE89FBE697DA80"
  405.     Mx = SPACE$(57) ' Mx  Š di 57 bytes / Mx is of 57 bytes
  406.     FOR i% = 1 TO 57
  407.         ' virtuosismo che carica codici esadecimali in Mx suddivisi nelle due stringhe
  408.         ' virtuosity it loads Hexadecimal codexes in Mx broke down them in two strings
  409.         H$ = CHR$(VAL("&H" + MID$(m$, i%, 1) + MID$(n$, i%, 1)))
  410.         MID$(Mx, i%, 1) = H$
  411.     NEXT i%
  412. IF c% = 0 THEN '  se deve spegnerlo/ if it must turn off
  413.     'usa interrupt scritto in Mx per il mouse tramite call absolute
  414.     ' it uses interrupt written in Mx for mouse by call absolute
  415.     CALL ABSOLUTE(2, click, cH, cV, SADD(Mx))
  416.     Status = 0
  417.     EXIT SUB
  418. ' se Š spento il mouse lo accende / if mouse is off, it turn on
  419. 'usa interrupt scritto in Mx per il mouse tramite call absolute
  420. ' it uses interrupt written in Mx for mouse by call  absolute
  421. IF Status = 0 THEN CALL ABSOLUTE(1, click, cH, cV, SADD(Mx))
  422. Status = 1
  423. ' rileva il mouse/ it detects mouse
  424. 'usa interrupt scritto in Mx per il mouse tramite call absolute
  425. ' it uses interrupt written in Mx for mouse by call absolute
  426. CALL ABSOLUTE(3, click, cH, cV, SADD(Mx))
  427. ' la variabile click Š True se l'utente ha cliccato
  428. 'variable click is True if user have made click
  429.  
  430. ' prende input / get input
  431. SUB GetUserSignal
  432.     IF 0 THEN ' Set to 1 for Debugging printout, otherwise 0
  433.         LOCATE 2, 1
  434.         PRINT click; "<Click"
  435.         PRINT cH; "ch (Horizontal)"
  436.         PRINT cV; "cv (Verticle)"
  437.     END IF
  438.     EnableMouse 1 ' attiva mouse  / it enables mouse
  439.     IF click > 0 THEN
  440.         ' se c'Š click la conservo in K% e aspetto che il tasto sia rilasciato
  441.         ' if there is click I store it in k% and I wait until button is released
  442.         k% = click
  443.         WHILE click <> 0: EnableMouse 1: WEND
  444.         click = k%
  445.         EXIT DO ' esce dal loop esterno / it exits from outer loop
  446.     END IF
  447.     cC = INKEY$ ' utente pu•  uscire premendo un tasto / user can exit pressing a key
  448. LOOP WHILE cC = ""
  449. EnableMouse 0 ' spegne il mouse / it turns off mouse
  450.  
  451. ' verifica se O ha vinto / it verifies if O won
  452. FUNCTION OWin% (b1 AS INTEGER, b2 AS INTEGER, b3 AS INTEGER, l AS INTEGER)
  453. IF zO(b1) = 0 OR zO(b2) = 0 OR zO(b3) = 0 THEN EXIT FUNCTION ' se una celle Š vuota esce / if one of these cells is void it exits
  454. Winner l ' evidenzia graficamente il tris / it marks up graphically tris
  455. OWin% = -1
  456.  
  457. SUB Winner (Lineup AS INTEGER) 'evidenzia il tris con una linea/ it shows tris by a line
  458. SELECT CASE Lineup
  459.     CASE 1: LINE (200, 140)-(440, 142), 14, BF: LINE (200, 143)-(440, 144), 0, B
  460.     CASE 2: LINE (200, 240)-(440, 242), 14, BF: LINE (200, 243)-(440, 244), 0, B
  461.     CASE 3: LINE (200, 340)-(440, 342), 14, BF: LINE (200, 343)-(440, 344), 0, B
  462.     CASE 4: LINE (220, 120)-(222, 360), 14, BF: LINE (223, 120)-(223, 360), 0
  463.     CASE 5: LINE (320, 120)-(322, 360), 14, BF: LINE (323, 120)-(323, 360), 0
  464.     CASE 6: LINE (420, 120)-(422, 360), 14, BF: LINE (423, 120)-(423, 360), 0
  465.     CASE 7: PSET (200, 120), 14: DRAW "F240 d H240 d F240 d H240 d C0 F240 d H240"
  466.     CASE 8: PSET (440, 120), 14: DRAW "G240 d E240 d G240 d E240 d C0 G240 d E240"
  467.  
  468. ' disegna la cella con simbolo se symbol Š 0 o 1 o la cella vuota se symbol Š 2
  469. ' it draws cell with symbol if symbol is 0 or 1 or cell void if symbol is 2
  470. SUB xo (Row AS INTEGER, Col AS INTEGER, symbol AS INTEGER)
  471. x = (Col - 1) * 100 + 180
  472. y = (Row - 1) * 100 + 100
  473. Index = symbol * 3000
  474. IF Index < 6000 THEN
  475.     PUT (x, y), SymbolBOX(Index), PSET
  476.     LINE (x, y)-(x + 80, y + 80), 1, BF
  477.  
  478. 'verifica che X ha fatto tris / it verifies if X have got tris
  479. FUNCTION XWin% (b1 AS INTEGER, b2 AS INTEGER, b3 AS INTEGER, l AS INTEGER)
  480. IF zX(b1) = 0 OR zX(b2) = 0 OR zX(b3) = 0 THEN EXIT FUNCTION ' se una delle celle Š  vuota esce/ if one of these cells is voit it exits
  481. Winner l ' evidenzia grafica del tris / it marks up graphically the tris
  482. XWin% = -1
  483.  
  484.  
Title: Re: QBasic OS
Post by: EricE on March 30, 2020, 09:55:41 am
Thank you TempodiBasic.
Title: Re: QBasic OS
Post by: EricE on April 03, 2020, 01:25:04 am
The source code for the MMURTL V1.0 operating system is available for download.
A whole book in pdf form about MMURTL can also be downloaded.

http://www.ipdatacorp.com/mmurtl/ (http://www.ipdatacorp.com/mmurtl/)

Both OS and book are by the same author who wrote "Developing Your own 32 Bit Operating System" published in 1995.
There probably are some good ideas contained in both the book and source code.