Author Topic: QBasic OS  (Read 7580 times)

0 Members and 1 Guest are viewing this topic.

Offline qbkiller101

  • Newbie
  • Posts: 73
    • View Profile
QBasic OS
« 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)

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: QBasic OS
« Reply #1 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
« Last Edit: March 24, 2020, 11:01:24 am by TempodiBasic »
Programming isn't difficult, only it's  consuming time and coffee

Offline luke

  • Administrator
  • Seasoned Forum Regular
  • Posts: 324
    • View Profile
Re: QBasic OS
« Reply #2 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.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: QBasic OS
« Reply #3 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. ;)
Programming isn't difficult, only it's  consuming time and coffee

Offline qbkiller101

  • Newbie
  • Posts: 73
    • View Profile
Re: QBasic OS
« Reply #4 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



Offline qbkiller101

  • Newbie
  • Posts: 73
    • View Profile
Re: QBasic OS
« Reply #5 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

Offline TerryRitchie

  • Seasoned Forum Regular
  • Posts: 495
  • Semper Fidelis
    • View Profile
Re: QBasic OS
« Reply #6 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.
« Last Edit: March 25, 2020, 12:18:10 pm by TerryRitchie »
In order to understand recursion, one must first understand recursion.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: QBasic OS
« Reply #7 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$
« Last Edit: March 25, 2020, 03:14:06 pm by bplus »

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Re: QBasic OS
« Reply #8 on: March 25, 2020, 12:43:37 pm »
Very helpful suggestions from Terry.

Offline qbkiller101

  • Newbie
  • Posts: 73
    • View Profile
Re: QBasic OS
« Reply #9 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

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: QBasic OS
« Reply #10 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
« Last Edit: March 25, 2020, 03:25:26 pm by bplus »

Offline qbkiller101

  • Newbie
  • Posts: 73
    • View Profile
Re: QBasic OS
« Reply #11 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.  


Offline qbkiller101

  • Newbie
  • Posts: 73
    • View Profile
Re: QBasic OS
« Reply #12 on: March 26, 2020, 07:43:15 am »
Unfortunately the website doesnt exist

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: QBasic OS
« Reply #13 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
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline EricE

  • Forum Regular
  • Posts: 114
    • View Profile
Re: QBasic OS
« Reply #14 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