My computer's water cooler died so my computer can't function right now without major heat issues and throttling. No coding for me until I get it fixed, unfortunately. Also, no video until then. I actually had plans on doing it yesterday evening and that's when it broke.
Screen _NewImage(800, 600, 32)
Dim As Long block
block = _NewImage(80, 40, 32)
_Dest block
For y = 0 To 40
Line (0, y)-(100, y), midInk~&(80, 0, 0, 255, 100, 100, 1 - y / 40), BF
Next
_Dest 0
r = 230: a = 0
Do
x = 410 + r * 1.5 * Cos(a): y = 300 + r * Sin(a)
_PutImage (x - 50, y - 20), block, 0
a = a + .002
_Limit 1000
Loop Until a >= _Pi(2.47)
Well, yes, but this one has one or two features that I've never seen in other word-games, so at the risk of overloading this genre of Programs (and the mentalities of the non-lexophile group), here it is.
It's attached as a .zip file, with the dictionary folder Wordlists, which should be in the same folder as the .bas file.
Color 14: Locate 8, 38: Print "Worm": Print: Print Tab(22);: Color 15: Print " An original word-game by Phil Taylor"
Print
Color 14
Print Tab(17); "Would you like to read the instructions (Y/N) ?"
Instrs:
_KeyClear: k = 0
While k < 1: _Limit 30: k = _KeyHit: Wend
If k <> 78 And k <> 110 Then instructions
Cls
name$(1) = "PLAYER 1": name$(2) = "PLAYER 2": winscore = 200
Locate 10, 9
Print " Accept defaults PLAYER 1, PLAYER 2, Win-level 200 points (Y/N) ?"
_KeyClear: k = 0
While k < 1: _Limit 30: k = _KeyHit: Wend
If k = 89 Or k = 121 Then name$(1) = "PLAYER 1": name$(2) = "PLAYER 2": winscore = 200: GoTo SetUpGame
_KeyClear
wipe "10"
Locate 10, 10: Print "Name for first player (enter for default PLAYER 1): ";
Input n$
If Len(n$) > 1 Then name$(1) = UCase$(n$)
wipe "10"
Locate 10, 10: Print "Name for second player (enter for default PLAYER 2) ";
Input n$
If Len(n$) > 1 Then name$(2) = UCase$(n$)
wipe "10"
Locate 10, 13: Print "Winning score (1=100 to 9=900, enter for default 100):";
_KeyClear: k = 0
While k < 1: _Limit 30: k = _KeyHit: Wend
If k < 49 Or k > 57 Then winscore = 100 Else winscore = (k - 48) * 100
wipe "10"
NewWord:
If score(1) >= winscore Or score(2) >= winscore Then
Cls: Locate 10, 32: Print "We have a winner!"
Print: Print Tab(31); name$(1), score(1); Tab(31); name$(2), score(2)
Sleep
System
End If
wrd$ = Chr$(Int(Rnd * 26) + 65): csrh = 320 ' wrd$ is random letter at start
PlayerUp:
Color 14
Locate 1, 3: Print name$(1); Space$(4); score(1); Tab(30); name$(plr); " playing"; Tab(64); name$(2); Space$(4); score(2)
cut = Int((Len(wrd$) + 1) / 2): wrdpos = 40: picked = 0: flipped = 0 ' cut is number of letters at left of cursor, changes each time a letter is added
wipe "10"
Locate 10, wrdpos: Print wrd$
ShowChoices:
Color 14
Locate 1, 3: Print name$(1); Space$(4); score(1); Tab(34); name$(plr); " playing"; Tab(64); name$(2); Space$(4); score(2)
Locate 2, 33: Print "Winning Score:"; winscore
Color 15: Locate 14, 26: Print "A-Z to select a letter to add"
If picked = 0 Then Color 8
Locate 15, 6: Print "Use Left/Right arrows to change its position, then up-arrow to place it": Color 15
If Len(wrd$) < minsize Or flipped = 1 Then Color 8
Locate 16, 7: Print "1 to Claim a word 2 to Challenge a group": Color 15
If Len(wrd$) < minsize Or flipped = 1 Then Color 8
Locate 16, 53: Print "3 to Concede this round": Color 15
If Len(wrd$) < 2 Then Color 8
Locate 17, 27: Print "Down-arrow to flip the word": Color 15
Locate 18, 32: Print "Esc to close game"
Locate 19, 57: Print ""
Color 15: Locate 12, 40: Print "?"
Case 65 To 90, 97 To 122 ' letter
If picked = 0 Then ' as long as letter not already picked...
picked = 1
letr$ = UCase$(Chr$(choice))
Locate 12, 40: Print letr$
Locate 15, 6: Print "Use Left/Right arrows to change its position, then up-arrow to place it"
GoTo GetChoice
End If
Case Is = 19200 ' left
If picked = 0 Then GoTo GetChoice ' if no letter picked yet, ignore
If cut > 0 Then ' if csr not beyond left limit...
wipe "11" ' remove csr...
csrh = csrh - 8: cut = cut - 1 ' reposition cut position and csr
End If
GoTo GetChoice
Case Is = 19712 ' right
If picked = 0 Then GoTo GetChoice ' if no letter picked yet, ignore
If cut < Len(wrd$) Then ' if csr not beyond right limit...
wipe "11" ' remove csr...
csrh = csrh + 8: cut = cut + 1 ' reposition cut position and csr
End If
GoTo GetChoice
Case Is = 18432 ' up (place letter)
flipped = 0
If picked = 1 Then
wrd$ = Left$(wrd$, cut) + letr$ + Right$(wrd$, Len(wrd$) - cut)
cut = Int((Len(wrd$) + 1) / 2)
wrdpos = 41 - cut
Locate 10, wrdpos: Print wrd$
picked = 0: flipped = 0
wipe "111617 "
csrh = 320
Locate 12, 40: Print "?"
letr$ = ""
If plr = 1 Then plr = 2 Else plr = 1
wipe "14151719"
Color 15: Locate 12, 40: Print "?"
End If
GoTo ShowChoices
Case Is = 49 ' claim word
If Len(wrd$) >= minsize And flipped = 0 Then
wordval = 0
For a = 1 To Len(wrd$): wordval = wordval + a: Next
Locate 5, 35: Print "Points Value is"; wordval
DictionaryCheck:
If _DirExists("WordLists") Then
found = 0
srch$ = "WordLists/" + Left$(wrd$, 1) ' set up file to be searched for try$
Open srch$ For Input As #1
While Not EOF(1)
Input #1, dictword$
If UCase$(dictword$) = wrd$ Then
found = 1
Exit While
End If
Wend
Close #1
Else
Locate 6, 10: Print "Is this word accepted (y/n)"
_KeyClear: k = 0
While k < 1
k = _KeyHit
Wend
If k = 110 Then found = 0
End If
If found = 0 Then
wipe "0607"
Locate 7, 35: Color 12: Print wrd$; " not found!"
If plr = 1 Then plr = 2 Else plr = 1
score(plr) = score(plr) + wordval
Else score(plr) = score(plr) + wordval
End If
Locate 9, 30: Print name$(plr); " scores"; wordval; " points"
Sleep 2
wipe "050709"
Color 14
GoTo NewWord
Else
GoTo GetChoice
End If
Case Is = 50 ' challenge word
If Len(wrd$) >= minsize And flipped = 0 Then
found = 0
wordval = 0: tryval = 0
For a = 1 To Len(wrd$): wordval = wordval + a: Next
Locate 6, 30: Print name$(plr); " challenges this group!"
If plr = 1 Then plr = 2 Else plr = 1
Print Tab(15); name$(plr); " Please type a word that contains the group";
_KeyClear
Print Tab(35);: Color 15: Input try$
try$ = UCase$(try$)
If try$ < "A" Or try$ > "Z" Then GoTo BadTry
For a = 1 To Len(try$): tryval = tryval + a: Next
If tryval > wordval Then wordval = tryval
DictSearch:
If _DirExists("WordLists") Then
found = 0
srch$ = "WordLists/" + Left$(try$, 1) ' set up file to be searched for try$
Open srch$ For Input As #1
While Not EOF(1)
Input #1, dictword$
If UCase$(dictword$) = try$ Then
found = 1
Exit While
End If
Wend
Close #1
Else
Locate 6, 10: Print "Is this word accepted (y/n)"
_KeyClear: k = 0
While k < 1
k = _KeyHit
Wend
If k = 110 Then found = 0
End If
BadTry:
If found = 0 Then
wipe "07"
Locate 7, 35: Color 12: Print try$; " Not found!"
If plr = 1 Then plr = 2 Else plr = 1
score(plr) = score(plr) + wordval
Else score(plr) = score(plr) + wordval
End If
Locate 9, 30: Print name$(plr); " scores"; wordval; " points"
Sleep 2
wipe "060709"
Color 14
GoTo NewWord
Else
GoTo GetChoice
End If
Case Is = 51 ' concede word
If Len(wrd$) >= minsize And flipped = 0 Then
wipe "0607080914151719"
wordval = 0
For a = 1 To Len(wrd$): wordval = wordval + a: Next
Locate 6, 30: Print name$(plr); " concedes this round!"
If plr = 1 Then plr = 2 Else plr = 1
score(plr) = score(plr) + wordval
Locate 9, 30: Print name$(plr); " scores"; wordval; " points"
Sleep 2
wipe "0506070809"
Color 14
GoTo NewWord
Else
GoTo GetChoice
End If
GoTo NewWord
Case Is = 20480 ' flip word
If picked = 0 Then
If flipped = 1 Then GoTo GetChoice
Locate 17, 27: Color 8: Print "Down-arrow to flip the word": Color 15
reverse$ = ""
For a = Len(wrd$) To 1 Step -1
reverse$ = reverse$ + Mid$(wrd$, a, 1)
Next
wrd$ = reverse$
flipped = 1
cut = Int((Len(wrd$) + 1) / 2): wrdpos = 41 - cut
GoTo GetChoice
End If
Case Else
GoTo GetChoice
End Select
Sub instructions
Cls: Color 14
Print Tab(32); "Worm Instructions"
Color 15
Print " A random letter is presented, and the players take turns to add one letter to"
Print " it, building towards a word, but avoiding completing it. The letter may be"
Print " placed at either end, or anywhere inside the group, thus exending the "; Chr$(34); "Worm"; Chr$(34); "."
Print
Print " If a player recognizes a completed word they may claim it, and gain points."
Print " If successful, they gain points based on its length but if not, their opponent"
Print " gains the points."
Print " The group may also be Flipped (reversed) before adding the letter (the result"
Print " of the Flip can not be claimed as a word)."
Print
Print " If they suspect that the group is not part of a real word, they may challenge,"
Print " and their opponent must then type a complete word containing the group. If"
Print " they can"; Chr$(39); "t provide a real word, the challenger gains points based on either"
Print " the size of the group or the length of their attempt, whichever is greater."
Print
Print " If a player thinks that any word formed by continuing to expand the group will"
Print " cost points, they may concede, and their opponent gains points based on the"
Print " size of the group thus far. This can help to avoid losing even more points."
Print
Print " The game ends when one player reaches the pre-set winning score."
Color 14: Print Tab(28); "Press a key to continue."
Sleep
Cls
Print
End Sub
Sub wipe (ln$)
For a = 1 To Len(ln$) - 1 Step 2
Locate Val(Mid$(ln$, a, 2)): Print Space$(80)
Next
End Sub
Sub Keypress
End Sub
Sub DictSearch
wrd$ = try$
srch$ = "WordLists/" + Left$(wrd$, 1)
wipe "14151719"
Open srch$ For Input As #1
While Not EOF(1)
Input #1, dictword$
If UCase$(dictword$) = wrd$ Then
wipe "07"
Locate 7, 35: Color 14: Print wrd$; " found!"
found = 1
Exit While
End If
Wend
Close #1
End Sub
I have a tutorial user that has reported my pixel perfect collision routines are not working in v3.5.0 but work fine in v3.4.1 but I can't replicate this.
The code below I've tested in the following and it works fine:
- Windows 7 SP2 and QB64PE v3.4.1 and v3.5.0
- The latest version of Linux Mint and QB64PE v3.5.0
For those of you with different versions of Windows, Linux, and MacOS would you kindly run the code below and let me know what you find out? The ZIP file attached contains the code and the two image files needed to run it.
Code: (Select All)
'** Pixel Perfect Collision Demo #5
Type TypeSPRITE ' sprite definition
image As Long ' sprite image
mask As Long ' sprite mask image
x1 As Integer ' upper left X
y1 As Integer ' upper left Y
x2 As Integer ' lower right X
y2 As Integer ' lower right Y
End Type
Type TypePOINT
x As Integer
y As Integer
End Type
Dim RedOval As TypeSPRITE ' red oval images
Dim GreenOval As TypeSPRITE ' green oval images
Dim Intersect As TypePOINT
RedOval.image = _LoadImage("redoval.png", 32) ' load red oval image image
GreenOval.image = _LoadImage("greenoval.png", 32) ' load green oval image
MakeMask RedOval ' create mask for red oval image
MakeMask GreenOval ' create mask for green oval image
Screen _NewImage(640, 480, 32) ' enter graphics screen
_MouseHide ' hide the mouse pointer
GreenOval.x1 = 294 ' green oval upper left X
GreenOval.y1 = 165 ' green oval upper left Y
Do ' begin main program loop
_Limit 30 ' 30 frames per second
Cls ' clear screen
While _MouseInput: Wend ' get latest mouse information
_PutImage (GreenOval.x1, GreenOval.y1), GreenOval.image ' display green oval
_PutImage (RedOval.x1, RedOval.y1), RedOval.image ' display red oval
RedOval.x1 = _MouseX ' record mouse X location
RedOval.y1 = _MouseY ' record mouse Y location
If PixelCollide(GreenOval, RedOval, Intersect) Then ' pixel collision?
Locate 2, 36 ' yes, position text cursor
Print "COLLISION!" ' report collision happening
Circle (Intersect.x, Intersect.y), 4, _RGB32(255, 255, 0)
Paint (Intersect.x, Intersect.y), _RGB32(255, 255, 0), _RGB32(255, 255, 0)
End If
_Display ' update screen with changes
Loop Until _KeyDown(27) ' leave when ESC key pressed
System ' return to operating system
'------------------------------------------------------------------------------------------------------------
Sub MakeMask (Obj As TypeSPRITE)
'--------------------------------------------------------------------------------------------------------
'- Creates a negative mask of image for pixel collision detection. -
'- -
'- Obj - object containing an image and mask image holder -
'-------------------------------------------------------------------
Dim x%, y% ' image column and row counters
Dim cc~& ' clear transparent color
Dim Osource& ' original source image
Dim Odest& ' original destination image
Obj.mask = _NewImage(_Width(Obj.image), _Height(Obj.image), 32) ' create mask image
Osource& = _Source ' save source image
Odest& = _Dest ' save destination image
_Source Obj.image ' make object image the source
_Dest Obj.mask ' make object mask image the destination
cc~& = _RGB32(255, 0, 255) ' set the color to be used as transparent
For y% = 0 To _Height(Obj.image) - 1 ' cycle through image rows
For x% = 0 To _Width(Obj.image) - 1 ' cycle through image columns
If Point(x%, y%) = cc~& Then ' is image pixel the transparent color?
PSet (x%, y%), _RGB32(0, 0, 0, 255) ' yes, set corresponding mask image to solid black
Else ' no, pixel is part of actual image
PSet (x%, y%), cc~& ' set corresponding mask image to transparent color
End If
Next x%
Next y%
_Dest Odest& ' restore original destination image
_Source Osource& ' restore original source image
_SetAlpha 0, cc~&, Obj.image ' set image transparent color
_SetAlpha 0, cc~&, Obj.mask ' set mask transparent color
End Sub
'------------------------------------------------------------------------------------------------------------
Function PixelCollide (Obj1 As TypeSPRITE, Obj2 As TypeSPRITE, Intersect As TypePOINT)
'--------------------------------------------------------------------------------------------------------
'- Checks for pixel perfect collision between two rectangular areas. -
'- Returns -1 if in collision -
'- Returns 0 if no collision -
'- -
'- obj1 - rectangle 1 coordinates -
'- obj2 - rectangle 2 coordinates -
'---------------------------------------------------------------------
Dim x1%, y1% ' upper left x,y coordinate of rectangular collision area
Dim x2%, y2% ' lower right x,y coordinate of rectangular collision area
Dim Test& ' overlap image to test for collision
Dim Hit% ' -1 (TRUE) if a collision occurs, 0 (FALSE) otherwise
Dim Osource& ' original source image handle
Dim p~& ' pixel color being tested in overlap image
If Obj1.x2 >= Obj2.x1 Then ' rect 1 lower right X >= rect 2 upper left X ?
If Obj1.x1 <= Obj2.x2 Then ' rect 1 upper left X <= rect 2 lower right X ?
If Obj1.y2 >= Obj2.y1 Then ' rect 1 lower right Y >= rect 2 upper left Y ?
If Obj1.y1 <= Obj2.y2 Then ' rect 1 upper left Y <= rect 2 lower right Y ?
If Obj2.x1 <= Obj1.x1 Then x1% = Obj1.x1 Else x1% = Obj2.x1 ' calculate overlapping
If Obj2.y1 <= Obj1.y1 Then y1% = Obj1.y1 Else y1% = Obj2.y1 ' square coordinates
If Obj2.x2 <= Obj1.x2 Then x2% = Obj2.x2 Else x2% = Obj1.x2
If Obj2.y2 <= Obj1.y2 Then y2% = Obj2.y2 Else y2% = Obj1.y2
Test& = _NewImage(x2% - x1% + 1, y2% - y1% + 1, 32) ' make overlap image
_PutImage (-(x1% - Obj1.x1), -(y1% - Obj1.y1)), Obj1.image, Test& ' place image 1
_PutImage (-(x1% - Obj2.x1), -(y1% - Obj2.y1)), Obj2.mask, Test& ' place image mask 2
'** enable the line below to see a visual represenation of mask on image
'_PUTIMAGE (x1%, y1%), Test&
x2% = x1%
y2% = y1%
y1% = 0 ' reset row counter
Osource& = _Source ' record current source image
_Source Test& ' make test image the source
Do ' begin row (y) loop
x1% = 0 ' reset column counter
Do ' begin column (x) loop
p~& = Point(x1%, y1%) ' get color at current coordinate
'** if color from object 1 then a collision has occurred
If p~& <> _RGB32(0, 0, 0, 255) And p~& <> _RGB32(0, 0, 0, 0) Then
Hit% = -1
Intersect.x = x1% + x2% ' return collision coordinates
Intersect.y = y1% + y2%
End If
x1% = x1% + 1 ' increment to next column
Loop Until x1% = _Width(Test&) Or Hit% ' leave when column checked or collision
y1% = y1% + 1 ' increment to next row
Loop Until y1% = _Height(Test&) Or Hit% ' leave when all rows checked or collision
_Source Osource& ' restore original destination
_FreeImage Test& ' test image no longer needed (free RAM)
End If
End If
End If
End If
PixelCollide = Hit% ' return result of collision check
This is from James D Jarvis, a handy way to make random numbers centered and dense around a center point andtapering off within a range. Here my test code I made for this, one for Integers and one for floats, single is assumed Type.
CW stands for Center Weight:
Code: (Select All)
_Title "rndCWI function" 'b+ 2023-01-20
Dim As Long low, high
high = 5
low = -high
Dim As Long a(low - 1 To high + 1)
For i = 1 To 100000
r = rndCWI(0, high)
a(r) = a(r) + 1
Next
For i = low - 1 To high + 1
Print String$(Int(a(i) / 1000 + .5), "*"), a(i) / 1000, i
Next
' 2023-01-20
Function rndCWI (center, range) 'center +/-range weights to center
Dim As Long halfRange, c
halfRange = Int(range) + 1 'for INT(Rnd) round range in case not integer
c = Int(center + .5)
rndCWI = c + Int(Rnd * (halfRange)) - Int(Rnd * (halfRange))
End Function
' 2023-01-20
Function rndCW (C As Single, range As Single) 'center +/-range weights to center
rndCW = C + Rnd * range - Rnd * range
End Function
Just drop the I from rndCWI to test the float version.
This is a simple program that works like "Cowsay" Flatpak app. It associates a quotation with a silly ASCII picture of an animal or person or something else. It draws a balloon around the quotation. Maybe I should have added the option for "thought" which is fluffier cloud...
This requires at least two files:
personaje.txt - contains the ASCII art. Each "personality" should be separated by a single line which has only three dashes, no whitespace around it, only newline should follow it.
personajq.txt - contains the quotations, one per line.
A file could be asked for in interactive mode:
personaj1.txt - has the quotation that you prefer to give the personality which is not found in "personajq.txt". I wrote this program originally in Freebasic, and I'm not sure if "_CLIPBOARD$" function works on Linux. Otherwise for Windows the change to that function could be certainly done.
Also in interactive mode it's possible to load a text file of your choice to display the personality on the terminal.
This program does no special formatting for the personality, only for the balloon and caption inside. Its output is into the terminal to make it easier to copy and paste into a text editor to foul it up...
Run this program without parameters and it comes up with a random quotation and a random personality from the two files required for it. Otherwise type "help" after the program name to see what's in it for interactive mode.
I'm only including the source code. I leave it to your imagination to go looking for ASCII art and things to say...
Code: (Select All)
$CONSOLE:ONLY
OPTION _EXPLICIT
DIM AS INTEGER p, q, pl, ql, ff, m, n, i, rm, m1, m2
DIM AS STRING pfile, qfile, a, b, bl, ca, crlf
DIM ch AS _UNSIGNED _BYTE
REDIM qline(1 TO 1) AS STRING
REDIM pline(1 TO 1) AS STRING
$IF WIN THEN
crlf = CHR$(13) + CHR$(10)
$ELSEIF LINUX THEN
crlf = CHR$(10)
$ELSE
crlf = CHR$(13)
$END IF
RANDOMIZE TIMER
q = 1
p = 1
ca = COMMAND$(1)
IF ca = "" THEN
qfile = "personajq.txt"
pfile = "personaje.txt"
IF NOT _FILEEXISTS(pfile) THEN
PRINT "File NOT found: "; pfile
SYSTEM
END IF
IF NOT _FILEEXISTS(qfile) THEN
PRINT "File NOT found: "; qfile
SYSTEM
END IF
ql = 10
pl = 10
REDIM qline(1 TO ql) AS STRING
REDIM pline(1 TO pl) AS STRING
b = ""
ff = FREEFILE
OPEN pfile FOR INPUT AS ff
DO UNTIL EOF(ff)
LINE INPUT #ff, a
IF a = "---" THEN
pline(p) = b
b = ""
p = p + 1
IF p > pl THEN
pl = pl + 10
REDIM _PRESERVE pline(1 TO pl) AS STRING
END IF
ELSE
'for Windows concatenate "chr(13) + chr(10)" instead of just the latter
b = b + delundersinside$(a) + crlf
END IF
LOOP
CLOSE ff
IF b = "" THEN
p = p - 1
ELSE
b = b + delundersinside$(a) + crlf
END IF
ff = FREEFILE
OPEN qfile FOR INPUT AS ff
DO UNTIL EOF(ff)
LINE INPUT #ff, a
IF a <> "" THEN
qline(q) = a
q = q + 1
IF q > ql THEN
ql = ql + 10
REDIM _PRESERVE qline(1 TO ql) AS STRING
END IF
END IF
LOOP
CLOSE ff
ELSE
ca = LCASE$(ca)
IF ca = "help" THEN
PRINT quotesquiggle$("Accepted parameters are: ~say~, ~pers~, ~both~ (without double-quotes)")
SYSTEM
END IF
IF ca = "say" OR ca = "both" THEN
PRINT "Write what the personality has to say"
PRINT quotesquiggle$("or ~c~ (without double-quote) to get it from")
PRINT "(current-dir)/personaj1.txt:"
LINE INPUT b
IF b = "" THEN SYSTEM
IF b = "c" THEN
qfile = "personaj1.txt"
b = ""
ff = FREEFILE
OPEN qfile FOR INPUT AS ff
IF NOT EOF(ff) THEN LINE INPUT #ff, b
CLOSE ff
END IF
qline(1) = b
END IF
IF ca = "pers" OR ca = "both" THEN
PRINT "Enter the filename (in current dir) which contains the personality:"
LINE INPUT pfile
IF pfile = "" THEN END
IF NOT _FILEEXISTS(pfile) THEN
PRINT "Without a personality I cannot work!"
SYSTEM
END IF
b = ""
ff = FREEFILE
OPEN pfile FOR INPUT AS ff
DO UNTIL EOF(ff)
LINE INPUT #ff, a
b = b + a + crlf
LOOP
CLOSE ff
pline(1) = b
END IF
END IF
IF q = 1 THEN n = 1 ELSE n = INT(RND * q + 1)
a = qline(n)
b = ""
bl = ""
rm = -1
m = 1
FOR i = 1 TO LEN(a)
m = m + 1
ch = ASC(a, i)
IF ch = 32 AND m > 50 THEN
IF m > rm THEN rm = m
bl = ""
m = 1
ELSE
bl = bl + CHR$(ch)
END IF
NEXT
IF rm = -1 THEN
rm = m
ELSEIF m > rm THEN
rm = m
END IF
bl = ""
m = 1
FOR i = 1 TO LEN(a)
m = m + 1
ch = ASC(a, i)
IF ch = 32 AND m > 50 THEN
b = b + "|" + bl + SPACE$(rm - LEN(bl)) + "|" + crlf
bl = ""
m = 1
ELSE
bl = bl + CHR$(ch)
END IF
NEXT
IF bl <> "" THEN
b = b + "|" + bl + SPACE$(rm - LEN(bl)) + "|" + crlf
END IF
m1 = rm - (rm \ 2) - 1
m2 = rm - m1 - 2
b = " " + STRING$(rm, 45) + crlf + b + " " + STRING$(m1, 45) + "||" + STRING$(m2, 45) + crlf + SPACE$(m1 + 1) + "||"
PRINT b
IF p = 1 THEN n = 1 ELSE n = INT(RND * p + 1)
PRINT pline(n)
SYSTEM
FUNCTION quotesquiggle$ (sa AS STRING)
STATIC st AS STRING
st = sa
ReplaceString2 st, "~", CHR$(34), 0
quotesquiggle$ = st
END FUNCTION
SUB ReplaceString2 (tx AS STRING, sfind AS STRING, repl AS STRING, numtimes AS _UNSIGNED LONG)
DIM AS STRING s, t
DIM AS _UNSIGNED LONG ls, count, u
DIM goahead AS _BYTE
IF (tx = "") OR (sfind = "") OR (sfind = repl) OR (LEN(sfind) > LEN(tx)) THEN EXIT SUB
s = UCASE$(sfind): t = UCASE$(tx)
ls = LEN(s)
count = 0
goahead = 1
DO
u = INSTR(t, s)
IF u > 0 THEN
tx = LEFT$(tx, u - 1) + repl + MID$(tx, u + ls)
t = UCASE$(tx)
IF numtimes > 0 THEN count = count + 1: IF count >= numtimes THEN goahead = 0
ELSE
goahead = 0
END IF
LOOP WHILE goahead
END SUB
FUNCTION delundersinside$ (sa AS STRING)
STATIC st AS STRING, i AS LONG, ch AS _UNSIGNED _BYTE, fl AS _UNSIGNED _BYTE
st = SPACE$(LEN(sa))
fl = 0
FOR i = 1 TO LEN(st)
ch = asc(sa, i)
IF ch = 95 AND fl = 1 THEN
'mid$(st, i, 1) = " "
_CONTINUE
ELSEIF ch <> 95 AND fl = 0 THEN
fl = 1
END IF
MID$(st, i, 1) = CHR$(ch)
NEXT
delundersinside$ = RTRIM$(st)
END FUNCTION
EDIT: Made sure it could work on "any" OS. Didn't process properly the "---" as last line of "personaje.txt", fixed. Didn't format the last line of balloon properly, fixed.
EDIT #2: Added a function, for display of the "personality" that turns the underscores into spaces, the annoying ones that interfere with image view.