F# - Natural Sort Of Strings Containing Numbers - f#

Is there an F# equivalent of Sorting for Humans: Natural Sort Order? For example, reproducing the following example:
Actual (List.sort) : let strngLst = ["1-5"; "10-15"; "15-20"; "5-10"]
Expected : let strngLst = ["1-5"; "5-10"; "10-15"; "15-20"]
Please advise?

Based on the Python 3-liner in that article, I would do something like this:
open System
open System.Text.RegularExpressions
let sortNicely l =
let convert text =
match Int32.TryParse(text) with
| true, i -> Choice1Of2 i
| false, _ -> Choice2Of2 text
let alphanumKey key =
Regex("([0-9]+)").Split(key) |> Array.map convert
List.sortBy alphanumKey l
The main difference is the use of the Choice type. The Python version cleverly uses dynamic typing in convert: Python always considers an int to be less than a string, so convert can return either an int or a string and sort will do what we want. But in F# we need to be more explicit. I used a discriminated union because it does what we want too: a value of the first case (Choice1Of2) is always less than a value of the second case (Choice2Of2).

Based on #matekus' comment, possibly the most correct solution is to port the AlphaNum sort to F#, so:
let len = String.length
let isnum (s: string) i =
let c = s.Chars i
c >= '0' && c <= '9'
let chunk s f t = (f < len s) && (t < len s) && (isnum s f) = (isnum s t)
let chunkto s f =
let rec to_ s f e = if chunk s f e then to_ s f (e + 1) else e in to_ s f f
let int_of_string str =
let v = ref 0
if System.Int32.TryParse(str, v) then !v else 0
let alphanumcmp a b =
let rec chunkcmp a ai b bi =
let al, bl = len a, len b
if ai >= al || bi >= bl then compare al bl else
let ae, be = chunkto a ai, chunkto b bi
let sa, sb = a.Substring(ai, (ae-ai)), b.Substring(bi, (be-bi))
let cmp = if isnum a ai && isnum b bi then compare (int_of_string sa) (int_of_string sb) else compare sa sb
if cmp = 0 then chunkcmp a ae b be else cmp
in chunkcmp a 0 b 0
type AlphanumComparer() =
interface System.Collections.IComparer with
member this.Compare(x, y) =
alphanumcmp (x.ToString()) (y.ToString())
Test:
let names = [ "1000X Radonius Maximus"; "10X Radonius"; "200X Radonius"; "20X Radonius"; "20X Radonius Prime"; "30X Radonius"; "40X Radonius"; "Allegia 50 Clasteron"; "Allegia 500 Clasteron"; "Allegia 51 Clasteron"; "Allegia 51B Clasteron"; "Allegia 52 Clasteron"; "Allegia 60 Clasteron"; "Alpha 100"; "Alpha 2"; "Alpha 200"; "Alpha 2A"; "Alpha 2A-8000"; "Alpha 2A-900"; "Callisto Morphamax"; "Callisto Morphamax 500"; "Callisto Morphamax 5000"; "Callisto Morphamax 600"; "Callisto Morphamax 700"; "Callisto Morphamax 7000"; "Callisto Morphamax 7000 SE";"Callisto Morphamax 7000 SE2"; "QRS-60 Intrinsia Machine"; "QRS-60F Intrinsia Machine"; "QRS-62 Intrinsia Machine"; "QRS-62F Intrinsia Machine"; "Xiph Xlater 10000"; "Xiph Xlater 2000"; "Xiph Xlater 300"; "Xiph Xlater 40"; "Xiph Xlater 5"; "Xiph Xlater 50"; "Xiph Xlater 500"; "Xiph Xlater 5000"; "Xiph Xlater 58" ];;
names |> List.sortWith alphanumcmp |> printf "%A"
Results:
["10X Radonius"; "20X Radonius"; "20X Radonius Prime"; "30X Radonius";
"40X Radonius"; "200X Radonius"; "1000X Radonius Maximus";
"Allegia 50 Clasteron"; "Allegia 51 Clasteron"; "Allegia 51B Clasteron";
"Allegia 52 Clasteron"; "Allegia 60 Clasteron"; "Allegia 500 Clasteron";
"Alpha 2"; "Alpha 2A"; "Alpha 2A-900"; "Alpha 2A-8000"; "Alpha 100";
"Alpha 200"; "Callisto Morphamax"; "Callisto Morphamax 500";
"Callisto Morphamax 600"; "Callisto Morphamax 700"; "Callisto Morphamax 5000";
"Callisto Morphamax 7000"; "Callisto Morphamax 7000 SE";
"Callisto Morphamax 7000 SE2"; "QRS-60 Intrinsia Machine";
"QRS-60F Intrinsia Machine"; "QRS-62 Intrinsia Machine";
"QRS-62F Intrinsia Machine"; "Xiph Xlater 5"; "Xiph Xlater 40";
"Xiph Xlater 50"; "Xiph Xlater 58"; "Xiph Xlater 300"; "Xiph Xlater 500";
"Xiph Xlater 2000"; "Xiph Xlater 5000"; "Xiph Xlater 10000"]val it : unit = ()

Related

Attempt to call a nil value (field 'getn')

Could you guys help me fix this lua code?
I'm getting a problem on line 89 if IsMouseButtonPressed(1) and indexP < table.getn(weapon[indexW]) then getting the error attempt to call a nil value (field 'getn')
"it" is asking me to add more details, so I will just add some letters down here.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AK47 = {{0,0}, {-0.56, 0.92}, {-0.55, 0.79}, {-0.45, 0.82}, {-0.27, 1.01}, {0.06, 2.49}, {0.65, 2.16}, {0.78, 2.17}, {0.46, 2.5}, {-0.04, 3.86}, {-0.41, 3.39}, {-0.54, 3.39}, {-0.41, 3.86}, {-0.36, 4.06}, {-0.36, 3.58}, {-0.1, 3.57}, {0.41, 4.02}, {1.14, 4.42}, {1.56, 3.73}, {1.74, 3.69}, {1.7, 4.28}, {1.05, 3.73}, {0.74, 3.34}, {0.84, 3.3}, {1.37, 3.6}, {1.9, 2.64}, {2.28, 2.1}, {1.8, 2.17}, {0.47, 2.85}, {-0.97, 2.71}, {-1.86, 1.95}, {-2.51, 1.4}, {-2.92, 1.06}, {-5.4, 0.71}, {-4.89, -0.84}, {-4.96, -1.29}, {-5.62, -0.64}, {-3.39, -0.37}, {-3.3, -0.53}, {-2.72, 0.24}, {-1.64, 1.95}, {0.7, 1.73}, {2.42, 0.96}, {2.49, 0.98}, {0.92, 1.79}, {-0.99, 1.83}, {-1.91, 0.87}, {-2.42, 0.28}, {-2.54, 0.05}, {-3.53, -0.87}, {-3.0, -1.9}, {-2.94, -1.57}, {-3.34, 0.1}, {-0.75, 0.42}, {-0.58, 0.61}, {-0.28, 0.72}, {0.15, 0.75}, {3.19, 2.01}, {4.93, -0.32}, {5.85, -0.97}, {5.95, 0.06}, {2.62, 0.6}, {2.26, 0.72}, {2.18, 0.93}, {2.39, 1.23}, {1.91, 1.37}, {1.51, 1.5}, {1.56, 1.38}, {2.07, 1.0}, {3.51, 0.62}, {3.18, -0.16}, {3.2, -0.6}, {3.59, -0.7}, {5.44, -0.2}, {5.49, 0.1}, {4.17, -0.95}, {1.46, -3.35}, {-1.57, -2.44}, {-3.26, -1.15}, {-3.41, 0.33}, {-2.02, 2.01}, {0.28, 0.57}, {0.98, 0.12}, {1.12, 0.12}, {0.68, 0.57}, {0.02, 1.49}, {-0.72, 1.24}, {-1.17, 1.1}, {-1.35, 1.06}, {-1.35, 0.49}, {-1.54, 0.11}, {-1.19, 0.22}, {-0.28, 0.84}, {1.38, 1.16}, {2.36, -0.91}, {2.85, -1.41}, {2.87, -0.36}, {1.28, 0.36}, {1.21, 0.51}, {0.8, 0.73}, {0.06, 1.01}, {-1.64, 1.63}, {-2.58, -0.2}, {-3.09, -0.97}, {-3.17, -0.69}, {-4.36, -0.19}, {-3.85, -0.15}, {-3.81, -0.39}, {-4.24, -0.91}, {-6.19, -2.43}, {-5.14, -2.99}, {-5.16, -2.9}, {-6.26, -2.15}, {-1.9, -0.25}, {-1.69, 0.03}, {-1.71, 0.15}, {-1.93, 0.09}}
M4A4 = {{0,0}, {0.27, 1.1}, {0.24, 0.98}, {0.18, 1.12}, {0.16, 1.58}, {0.03, 1.42}, {-0.16, 1.58}, {-0.9, 2.81}, {-1.15, 2.42}, {-0.62, 2.84}, {0.71, 3.66}, {1.42, 3.17}, {0.72, 3.66}, {-0.77, 4.13}, {-1.54, 3.53}, {-1.48, 4.03}, {-1.55, 4.55}, {-1.24, 4.1}, {0.38, 4.49}, {2.06, 3.13}, {2.97, 2.07}, {3.13, 2.51}, {1.65, 2.3}, {1.35, 2.16}, {2.01, 1.87}, {4.02, 0.81}, {3.98, -0.19}, {2.91, 1.84}, {0.28, 1.96}, {-0.91, 1.83}, {-1.54, 1.67}, {-2.61, 1.79}, {-2.81, 0.8}, {-3.25, 0.37}, {-5.18, -0.21}, {-4.58, -1.06}, {-5.18, -0.88}, {-4.11, -0.07}, {-3.67, 0.14}, {-4.1, -0.18}, {-5.07, -1.48}, {-4.51, -1.72}, {-3.45, 0.38}, {-0.32, 0.53}, {0.04, 0.64}, {0.27, 0.64}, {1.69, 1.04}, {2.01, 0.46}, {0.71, 1.17}, {-1.18, 1.04}, {-2.05, -0.28}, {-2.26, -0.46}, {-2.93, -1.1}, {-2.62, -1.3}, {-1.82, 0.82}, {0.08, 0.52}, {0.59, 0.34}, {0.72, 0.25}, {4.48, 0.1}, {6.12, -0.65}, {6.58, 0.62}, {1.82, 0.98}, {1.43, 1.27}, {1.79, 1.05}, {4.5, 0.9}, {4.17, 0.02}, {4.65, 0.31}, {1.55, 0.35}, {1.37, 0.39}, {1.56, 0.31}, {2.47, 0.68}, {2.26, 0.52}, {1.03, -1.02}, {-1.23, -1.46}, {-2.51, -0.05}, {-1.82, 1.33}, {0.24, 1.0}, {1.2, 0.66}, {1.26, 0.8}, {0.67, 0.88}, {0.56, 0.82}, {0.81, 0.71}, {0.52, 0.23}, {0.51, 0.09}, {0.58, 0.01}, {0.76, -0.1}, {0.66, -0.21}, {0.74, -0.23}}
AUG = {{0,0}, {0.63, 0.67}, {0.57, 0.59}, {0.33, 0.79}, {-0.06, 0.62}, {-0.27, 0.53}, {-0.29, 0.6}, {-0.34, 0.96}, {-0.29, 0.86}, {-0.3, 0.97}, {-0.64, 2.07}, {-0.52, 1.86}, {-0.26, 2.13}, {0.18, 3.0}, {0.57, 2.65}, {0.67, 2.97}, {0.53, 3.41}, {0.51, 3.03}, {0.98, 3.28}, {1.18, 2.33}, {1.32, 1.95}, {1.29, 2.29}, {0.59, 1.79}, {0.4, 1.65}, {0.73, 1.72}, {1.58, 1.47}, {1.69, 1.12}, {0.66, 1.68}, {-1.09, 1.68}, {-2.08, 0.85}, {-2.04, 1.26}, {-0.68, 0.65}, {-0.53, 0.65}, {0.04, 0.72}, {1.27, 0.34}, {1.66, -0.7}, {1.52, 0.14}, {0.47, 0.78}, {0.0, 0.89}, {-0.43, 0.83}, {-2.08, 1.29}, {-2.46, 0.06}, {-2.74, -0.35}, {-3.85, -0.78}, {-3.29, -1.31}, {-3.65, -1.59}, {-3.06, -2.07}, {-2.68, -2.03}, {-2.87, 0.14}, {-0.3, 0.61}, {0.19, 0.8}, {0.02, 0.86}, {-0.3, 0.84}, {-0.41, 0.68}, {-0.67, 0.51}, {-0.99, 0.33}, {-0.96, 0.02}, {-0.4, -0.55}, {1.44, -1.32}, {3.05, 0.79}, {3.34, 0.85}, {3.32, 0.11}, {2.95, 0.13}, {3.24, 0.58}, {1.66, 0.26}, {1.46, 0.36}, {0.51, 1.02}, {-0.62, 0.68}, {-1.04, 0.16}, {-0.63, -0.51}, {0.76, -1.0}, {2.11, 0.14}, {2.28, -0.03}, {3.06, -1.23}, {2.64, -1.34}, {3.12, -0.96}, {2.22, -0.53}, {2.03, -0.24}, {1.01, 1.06}, {-0.89, 1.38}, {-2.38, 0.16}, {-2.63, 0.13}, {-1.88, 0.27}, {-1.7, 0.16}, {-1.45, 0.39}, {-0.21, 0.14}, {-0.16, 0.16}, {-0.18, 0.18}}
SG553 = {{0,0}, {-0.56, 1.34}, {-0.5, 1.2}, {-0.69, 1.27}, {-2.27, 2.8}, {-2.31, 2.28}, {-2.14, 2.87}, {-1.87, 4.11}, {-1.12, 3.9}, {-1.13, 4.42}, {-1.29, 4.98}, {-1.0, 4.47}, {-1.14, 5.02}, {-1.36, 5.54}, {-1.22, 4.93}, {-1.28, 5.55}, {-0.73, 6.22}, {-0.51, 5.58}, {-2.23, 5.6}, {-3.55, 2.59}, {-4.02, 1.51}, {-2.25, 3.06}, {1.53, 3.17}, {3.45, 2.22}, {2.02, 3.19}, {-0.54, 2.48}, {-1.56, 1.91}, {-2.1, 1.81}, {-2.59, 1.58}, {-2.61, 0.94}, {-2.73, 1.4}, {-1.08, 0.64}, {-0.9, 0.66}, {-0.35, 1.0}, {0.78, 0.98}, {1.4, 0.53}, {0.75, 0.98}, {-0.84, 1.3}, {-1.69, 0.71}, {-1.28, 1.22}, {0.28, 1.91}, {0.94, 1.77}, {-0.31, 1.5}, {-2.24, 0.51}, {-2.31, -1.29}, {-2.42, -1.74}, {-3.59, -2.94}, {-2.8, -3.15}, {-3.53, -3.04}, {-2.87, -1.56}, {-2.73, -1.06}, {-3.09, -1.14}, {-1.84, -0.31}, {-1.69, -0.23}, {-0.54, -0.99}, {4.26, -3.02}, {7.61, 2.5}, {8.4, 2.11}, {9.79, -0.58}, {8.69, -1.11}, {9.78, -0.94}, {7.46, -0.76}, {6.65, -0.54}, {7.3, 0.9}, {3.21, 1.27}, {2.62, 1.72}, {2.94, 1.94}, {2.62, 1.39}, {2.33, 1.25}, {2.4, 1.7}, {0.97, 1.19}, {0.73, 1.2}, {1.16, 0.88}, {3.64, 0.45}, {3.39, -0.87}, {3.8, -0.93}, {5.47, -1.88}, {4.93, -1.82}, {3.57, 1.82}, {-0.08, 1.49}, {-1.41, 1.18}, {-1.75, 1.09}, {-2.14, 1.27}, {-2.1, 0.77}, {-2.46, 0.43}, {-6.76, -0.03}, {-6.01, -1.16}, {-6.76, -1.25}}
M4A1S = {{0,0}, {0.18, 0.78}, {0.17, 0.68}, {0.15, 0.68}, {0.1, 0.79}, {0.03, 0.66}, {-0.01, 0.58}, {-0.05, 0.58}, {-0.1, 0.65}, {-0.46, 1.77}, {-0.6, 1.51}, {-0.53, 1.52}, {-0.25, 1.78}, {0.31, 2.44}, {0.76, 2.1}, {0.75, 2.1}, {0.3, 2.44}, {-0.4, 2.86}, {-0.83, 2.43}, {-0.99, 2.41}, {-0.86, 2.8}, {-0.92, 3.14}, {-0.92, 2.8}, {-0.47, 2.79}, {0.43, 3.09}, {1.19, 2.24}, {1.7, 1.58}, {1.94, 1.45}, {1.91, 1.86}, {1.03, 1.57}, {0.77, 1.5}, {0.86, 1.41}, {1.31, 1.28}, {2.45, 0.88}, {2.6, 0.06}, {2.34, 0.28}, {1.67, 1.53}, {0.28, 1.37}, {-0.38, 1.28}, {-0.83, 1.2}, {-1.08, 1.12}, {-1.62, 1.23}, {-1.68, 0.71}, {-1.83, 0.38}, {-2.08, 0.24}, {-3.29, -0.0}, {-2.88, -0.52}, {-2.89, -0.67}, {-3.3, -0.43}, {-2.59, -0.0}, {-2.28, 0.17}, {-2.28, 0.15}, {-2.59, -0.05}, {-3.17, -0.72}, {-3.01, -1.12}, {-2.59, -0.67}, {-1.93, 0.63}, {-0.17, 0.34}, {0.04, 0.37}, {0.18, 0.38}, {0.25, 0.37}, {1.07, 0.64}, {1.34, 0.23}, {1.09, 0.29}, {0.32, 0.81}, {-0.62, 0.84}, {-1.16, 0.08}, {-1.44, -0.27}, {-1.45, -0.21}, {-1.86, -0.52}, {-1.8, -0.88}, {-1.5, -0.44}, {-0.98, 0.81}, {0.04, 0.32}, {0.35, 0.18}, {0.48, 0.13}, {0.46, 0.18}}
FAMAS = {{0,0}, {-0.75, 0.66}, {-0.68, 0.59}, {-0.45, 0.83}, {0.06, 0.69}, {0.29, 0.62}, {0.1, 0.7}, {-0.86, 1.85}, {-1.31, 1.43}, {-1.07, 1.8}, {-0.53, 2.82}, {0.04, 2.6}, {0.1, 2.92}, {-0.27, 3.68}, {-0.18, 3.28}, {0.68, 3.53}, {1.75, 3.49}, {2.31, 2.7}, {2.89, 2.75}, {3.07, 1.81}, {3.0, 1.31}, {1.82, 2.52}, {-0.12, 2.33}, {-1.24, 1.93}, {-1.86, 1.77}, {-2.99, 1.84}, {-3.12, 0.89}, {-3.5, 1.0}, {-2.89, 1.16}, {-2.57, 1.01}, {-2.97, 0.87}, {-2.58, -0.09}, {-2.36, -0.31}, {-1.55, 1.11}, {0.11, 1.2}, {1.03, 0.93}, {1.34, 0.77}, {3.76, 1.22}, {3.67, 0.16}, {4.02, 0.6}, {2.01, 0.91}, {1.72, 1.0}, {2.06, 0.65}, {3.38, -0.16}, {3.0, -0.83}, {3.4, -0.48}, {1.01, 0.11}, {0.89, 0.21}, {1.01, 0.16}, {2.61, -0.21}, {2.34, -0.37}, {2.39, 0.54}, {0.93, 0.63}, {0.61, 0.82}, {0.09, 1.02}, {-0.45, 0.77}, {-0.8, 0.41}, {-0.97, 0.27}, {-4.59, -0.01}, {-4.21, -1.03}, {-3.75, 0.17}, {-0.71, 0.37}, {-0.52, 0.51}, {-0.01, 0.62}, {1.34, 0.82}, {1.89, -0.49}, {2.05, -0.73}, {2.67, -0.81}, {2.28, -1.02}, {2.47, -1.33}, {2.8, -1.73}, {2.37, -1.74}, {2.67, -1.94}}
UMP45 = {{0,0}, {-0.12, 1.13}, {-0.1, 1.01}, {-0.23, 1.11}, {-0.58, 1.4}, {-0.66, 1.19}, {-0.55, 1.41}, {-0.46, 2.96}, {-0.06, 2.7}, {-0.23, 3.01}, {-0.62, 3.81}, {-0.71, 3.36}, {-1.06, 3.71}, {-1.63, 3.93}, {-1.72, 3.4}, {-1.42, 3.99}, {-1.07, 4.44}, {-0.5, 4.04}, {0.53, 4.44}, {1.74, 3.1}, {2.32, 2.43}, {1.39, 3.16}, {-0.51, 2.07}, {-1.16, 1.75}, {-0.48, 2.06}, {0.81, 2.65}, {1.56, 2.05}, {2.15, 1.92}, {2.97, 1.91}, {3.0, 1.13}, {3.42, 1.15}, {2.61, 0.48}, {2.38, 0.3}, {1.86, 1.39}, {0.07, 0.57}, {-0.23, 0.57}, {-0.06, 0.63}, {0.69, 1.15}, {0.96, 0.86}, {0.73, 1.14}, {-0.09, 1.02}, {-0.34, 0.95}, {0.27, 0.77}, {1.47, 0.23}, {1.47, -0.89}, {1.64, -0.98}, {1.13, -0.72}, {1.02, -0.69}, {0.68, 0.29}, {-0.64, 1.63}, {-2.73, 0.53}, {-3.04, 0.41}, {-3.7, 1.09}, {-3.4, 0.73}, {-2.32, -0.69}, {-0.12, -0.38}, {0.15, -0.4}, {0.28, -0.38}, {1.79, -1.35}, {2.25, -0.81}, {2.59, -0.68}, {3.29, -1.36}, {3.04, -1.03}, {1.92, 1.27}, {-0.18, 0.62}, {-0.8, 0.32}, {-0.94, 0.21}, {-3.72, 0.48}, {-3.39, -0.32}, {-3.6, -0.71}, {-0.68, -0.19}, {-0.58, -0.23}, {-0.66, -0.26}}
MP7 = {{0,0}, {0.04, 0.6}, {0.06, 0.52}, {0.02, 0.52}, {-0.05, 0.59}, {-0.09, 0.45}, {-0.12, 0.39}, {-0.17, 0.37}, {-0.23, 0.4}, {-0.34, 0.46}, {-0.36, 0.36}, {-0.37, 0.35}, {-0.37, 0.44}, {-0.81, 1.23}, {-0.63, 1.13}, {-0.61, 1.15}, {-0.74, 1.28}, {-1.32, 1.82}, {-1.3, 1.53}, {-1.14, 1.6}, {-0.84, 2.03}, {-0.16, 2.21}, {0.42, 2.01}, {0.4, 2.0}, {-0.22, 2.19}, {-0.97, 1.85}, {-1.32, 1.38}, {-1.39, 1.35}, {-1.19, 1.76}, {-0.45, 1.75}, {-0.04, 1.68}, {-0.16, 1.6}, {-0.82, 1.5}, {-1.13, 0.79}, {-1.25, 0.28}, {-1.34, 0.15}, {-1.42, 0.39}, {-0.97, 0.31}, {-0.94, 0.25}, {-0.74, 0.4}, {-0.38, 0.76}, {0.22, 1.47}, {0.96, 1.09}, {1.4, 0.87}, {1.54, 0.81}, {2.39, 1.01}, {2.26, 0.47}, {2.34, 0.23}, {2.63, 0.29}, {2.39, 0.31}, {2.11, 0.2}, {2.11, 0.14}, {2.4, 0.14}, {2.04, -0.15}, {1.88, -0.36}, {1.75, -0.04}, {1.64, 0.82}, {0.42, 0.54}, {0.18, 0.62}, {-0.02, 0.67}, {-0.18, 0.7}, {-0.51, 0.93}, {-0.7, 0.66}, {-0.86, 0.53}, {-0.98, 0.54}, {-0.49, 0.23}, {-0.46, 0.14}, {-0.47, 0.12}, {-0.52, 0.17}, {-0.58, 0.14}, {-0.57, 0.09}, {-0.45, 0.18}, {-0.22, 0.42}, {0.21, 0.47}, {0.57, 0.24}, {0.63, 0.24}, {0.37, 0.46}, {0.03, 0.62}, {-0.17, 0.56}, {-0.36, 0.47}, {-0.52, 0.35}, {-1.94, 0.45}, {-1.81, -0.37}, {-1.84, -0.8}, {-2.02, -0.83}, {-2.72, -1.17}, {-2.32, -1.32}, {-2.27, -1.25}, {-2.57, -0.95}, {-0.52, -0.08}, {-0.47, 0.0}, {-0.47, 0.01}, {-0.53, -0.04}, {-1.43, -0.06}, {-1.38, 0.01}, {-1.13, -0.27}, {-0.66, -0.91}, {0.09, -0.32}, {0.36, -0.2}, {0.4, -0.2}, {0.23, -0.33}, {0.0, -0.3}, {-0.08, -0.29}, {-0.16, -0.21}, {-0.24, -0.05}, {-0.14, 0.14}, {0.03, 0.27}, {0.05, 0.3}, {-0.09, 0.25}, {-0.57, 0.22}, {-0.63, -0.1}, {-0.63, -0.11}, {-0.58, 0.21}, {-0.21, 0.31}, {-0.05, 0.35}, {0.01, 0.38}, {-0.03, 0.41}}
MP9 = {{0,0}, {-0.06, 1.42}, {-0.25, 1.37}, {-0.78, 1.07}, {-0.63, 1.11}, {0.59, 2.78}, {1.0, 2.79}, {-0.48, 4.4}, {-0.29, 4.37}, {2.43, 5.36}, {2.47, 5.35}, {0.26, 5.22}, {-0.92, 5.21}, {-2.59, 5.49}, {-1.39, 5.53}, {1.82, 3.97}, {3.44, 3.05}, {4.88, 3.09}, {5.55, 1.7}, {5.5, 0.56}, {5.56, -0.51}, {6.82, -3.0}, {5.91, -0.05}, {0.32, 2.2}, {-0.78, 2.69}, {0.66, 2.9}, {-0.23, 2.62}, {-5.22, 2.59}, {-6.44, 1.18}, {-3.31, 2.16}, {-3.27, 2.24}, {-4.45, 1.93}, {-4.56, 1.71}, {-3.43, 1.78}, {-3.57, 1.31}, {-5.25, 0.28}, {-5.24, -0.86}, {-8.97, -4.96}, {-5.99, -0.22}, {0.73, 0.86}, {1.83, 0.35}, {4.05, 0.95}, {4.15, 0.48}, {5.39, -0.03}, {4.94, 0.56}, {1.1, 0.4}, {0.39, 0.72}, {-3.55, 0.93}, {-5.12, -1.93}, {-6.55, -2.47}, {-6.59, -1.18}, {-1.54, 0.71}, {-1.43, 1.04}, {-3.35, 0.7}, {-1.94, 1.62}, {1.7, 1.68}, {3.05, 1.07}, {1.29, 1.25}, {1.19, 1.36}}
MAC = {{0,0}, {-0.82, 0.45}, {-0.73, 0.39}, {-0.66, 0.62}, {-0.38, 0.59}, {-0.2, 0.6}, {-0.03, 0.7}, {0.3, 1.08}, {0.57, 0.88}, {0.56, 1.03}, {0.7, 2.3}, {0.48, 2.09}, {0.78, 2.26}, {1.61, 2.97}, {1.72, 2.49}, {1.8, 2.88}, {2.11, 4.05}, {1.73, 3.67}, {1.86, 4.17}, {1.85, 3.48}, {1.61, 3.12}, {0.78, 3.72}, {-0.83, 3.03}, {-1.54, 2.59}, {-0.42, 2.98}, {1.07, 1.84}, {1.68, 1.26}, {1.58, 1.64}, {0.85, 1.84}, {0.49, 1.75}, {0.6, 1.95}, {0.93, 1.9}, {0.88, 1.68}, {0.43, 2.0}, {-0.16, 1.32}, {-0.46, 1.13}, {-0.59, 1.24}, {-0.29, 0.8}, {-0.3, 0.69}, {-0.53, 0.63}, {-1.46, 0.89}, {-1.52, 0.39}, {-1.75, 0.26}, {-3.53, 0.42}, {-3.18, 0.02}, {-3.56, -0.29}, {-5.85, -0.96}, {-5.23, -1.28}, {-3.24, -0.91}, {-0.31, -0.1}, {-0.28, -0.1}, {-0.31, -0.11}, {-2.34, -0.22}, {-2.42, -0.23}, {-0.93, -1.37}, {0.89, -0.29}, {1.49, 0.54}, {0.91, -0.29}, {-0.41, -0.78}, {-1.22, -0.21}, {-1.37, -0.14}, {-2.03, -0.36}, {-1.84, -0.12}, {-2.07, 0.06}, {-2.36, -0.15}, {-2.13, -0.01}, {-0.86, 1.18}, {1.45, 1.47}, {3.11, -0.47}, {3.4, -0.39}, {2.26, 0.29}, {2.0, 0.3}, {2.26, 0.27}, {2.72, 0.26}, {2.42, 0.17}, {2.73, 0.05}, {3.76, -0.62}, {3.35, -0.77}, {3.48, 0.62}, {0.8, 0.51}, {0.54, 0.67}, {-0.08, 0.74}, {-3.75, 1.42}, {-4.46, -1.43}, {-2.25, -2.49}, {0.19, -0.29}, {0.47, -0.07}, {0.51, -0.09}}
weapon = {AK47, M4A4, AUG, SG553, M4A1S, FAMAS, UMP45, MP7, MP9, MAC}
------------------------ Rate of Fire ----------------------
ak47_ROF = {delay = 100, interpolation = 4}
m4a4_ROF = {delay = 90, interpolation = 3}
aug_ROF = {delay = 90, interpolation = 3}
sg553_ROF = {delay = 90, interpolation = 3}
m4a1s_ROF = {delay = 100, interpolation = 4}
famas_ROF = {delay = 90, interpolation = 3}
ump_ROF = {delay = 90, interpolation = 3}
mp7_ROF = {delay = 80, interpolation = 4}
mp9_ROF = {delay = 70, interpolation = 2}
mac_ROF = {delay = 75, interpolation = 3}
weaponRof = {ak47_ROF, m4a4_ROF, aug_ROF, sg553_ROF, m4a1s_ROF, famas_ROF, ump_ROF, mp7_ROF, mp9_ROF, mac_ROF}
------------------- Weapon Sensitivity ---------------------
AKsen = 2.85
M4sen = 2.8
AUGsen = 4.7
SG553sen = 2.8
M4A1sen = 2.3
FAMsen = 3
UMPsen = 2.8
MP7sen = 3
MP9sen = 2.9
MACsen = 2.8
weaponSen = {AKsen, M4sen, AUGsen, SG553sen, M4A1sen, FAMsen, UMPsen, MP7sen, MP9sen, MACsen}
------------------------------------------------------------
indexW = 1 --index of weapon
indexP = 1 --index of Pattern
indexT = 1 -- 1 rifle / 2 smg
function OnEvent(event, arg)
EnablePrimaryMouseButtonEvents(true)
if IsMouseButtonPressed(2) then
indexW = indexW + 1
if indexT == 1 then
if indexW > 6 then
indexW = 1
end
end
if indexT == 2 then
if indexW > 10 then
indexW = 7
end
end
if indexW == 1 then
PressAndReleaseKey("insert")
end
if indexW == 2 then
PressAndReleaseKey("home")
end
if indexW == 3 then
PressAndReleaseKey("pageup")
end
if indexW == 4 then
PressAndReleaseKey("delete")
end
if indexW == 5 then
PressAndReleaseKey("end")
end
if indexW == 6 then
PressAndReleaseKey("pagedown")
end
if indexW == 7 then
PressAndReleaseKey("up")
end
if indexW == 8 then
PressAndReleaseKey("down")
end
if indexW == 9 then
PressAndReleaseKey("left")
end
if indexW == 10 then
PressAndReleaseKey("right")
end
end
while IsMouseButtonPressed(4) do
if IsMouseButtonPressed(1) and indexP < table.getn(weapon[indexW]) then
MoveMouseRelative(weapon[indexW][indexP][1]*weaponSen[indexW], weapon[indexW][indexP][2]*weaponSen[indexW])
Sleep(weaponRof[indexW].delay/weaponRof[indexW].interpolation)
indexP = indexP + 1
else
Sleep(10)
indexP = 1
end
if IsMouseButtonPressed(2) then
indexT = indexT + 1
if indexT > 2 then
indexT = 1
end
if indexT == 1 then
indexW = 1
PressAndReleaseKey("insert")
else
indexW = 7
PressAndReleaseKey("up")
end
Sleep(300)
OutputLogMessage(indexW)
end
end
indexP = 1
end
table.getn does not exist in more recent versions of Lua. Instead, use the length operator: #weapon[indexW].

Mysterious Out Of Memory Error In 6502 BASIC

I am trying to create a simple word search game that will put characters on a board on xpet in the VICE emulator using 6502 BASIC. I find that it used to work fine before I added the status indicator, but now it fails, running out of memory at 45, for more than 3 words. This is very strange, because the status indicator uses the same variables that the rest of the program uses, meaning that it should not take up any more space. Does anyone have any idea what could be causing this error? Is there a hidden bug?
1 uu = 0 : goto 600 : rem So you can just type run. uu=0: (toggle indicator on)
2 rem This is a simple wordsearch game generator
3 rem that takes words and creates a board and key from it.
4 rem Words can only be read/written top to bottom or left to right.
5 rem The board is a square between 3x3 and 21x21. More information at 12000.
8 print "Zero Words, terminating game..." : rem This small piece
9 end : rem of code here is what happens if you put 0 for the number of words.
10 rem Below is the default data (it's random). Hopefully it is enough.
11 data "rat","clam","ten","sip","lie","ugly","not","yet","thou","if"
12 data "dog","cat","no","yes","maybe","truck","car","trap","lamb"
13 data "three","long","short","two","one","zero","cow","cart","house"
14 data "hair","hall","heart","head","who","is","truth","false","cake"
15 data "five","six","seven","eight","nine","ten","good","bad","rad"
16 data "thy","art","short","long","potatoes","tomato","ramble"
17 data "crumble","shambles","lion","turtle","beach","breach"
18 data "data","read","bamboozle","words","list","assasin","off"
19 data "are","viking","knight","sword","random","treacherous","..."
21 rem If it is not enough data, the game will reach the "..." and
22 rem your game will be cut short (have less words). There are
23 rem about 70 to 100 words in this default list.
24 rem Do not remove the "...", or it will crash when you ask for
25 rem too many words (more than the number provided).
40 rem This is substring from le to ri where st$ goes from 0 to len-1
41 rem Left is inclusive and right is not inclusive.
42 rem Assumes that st$ exists; returns sr$. le and ri must also exit.
43 rem This encapsulates the mid function for ease of use.
45 le = le+1: rem: remember basic strings go from 1 to len
46 sr$ = mid$(st$,le,ri-le+1)
47 le = le-1: rem: we try to avoid outside effects
48 return
49 rem: A subroutine that returns a random
50 rem: Boolean (tosses a coin).
51 rem: It will return 0 or 1 randomly; output is in mr.
52 mn = 0: mx = 1
53 gosub 500
54 gosub 10000 : return
55 rem Assumes strings named s0$ and s1$ exist.
56 rem (these are the strings we search for an intersection)
57 s2$ = "": rem returns a string of the intersections in s2$.
58 for i = 0 to len(s0$)-1 : rem: for all characters in s0$
59 st$ = s0$: le = i : ri = i+1
60 gosub 40
61 ch$ = sr$ : rem temp var
62 for j = 0 to len(s1$)-1
63 le = j: ri = j+1: st$ = s1$
64 gosub 40
65 if ch$ = sr$ then s2$ = s2$ + ch$
66 next j
67 next i
68 gosub 10000 : return
99 rem Gets a random float.
100 mr = rnd(0)*(mx-mn)+mn
101 gosub 10000 : return
300 rem Scrambles the order of ps$().
301 for i = 0 to ip-1
302 mx = ip-1
303 mn = 0
304 gosub 500
305 sp$ = ps$(mr)
307 ps$(mr) = ps$(i)
309 ps$(i) = sp$
311 next i
312 gosub 10000 : return
499 rem Random Integer subroutine.
500 mx = mx+1 : rem increment here so top is inclusive
501 gosub 100 : rem run exclusive floating point version
502 mr = int(mr) : rem we turn it into an integer via truncation
503 mx = mx - 1 : rem reset mx, to avoid side effects
504 gosub 10000 : return
505 goto 535
530 rem This subroutine returns gp$(), a two
531 rem dimensional array of all the words where
532 rem for each value of ps$() where a word is
533 rem the list in gp$() of that value has the words
534 rem that match/intersect with it.
535 dim gp$(ip-1,ip-1)
536 for l = 0 to ip-1
537 ix = 0
538 for cc = 0 to ip-1
539 s0$ = ps$(l)
540 s1$ = ps$(cc)
541 gosub 55
543 if s2$ = "" then goto 545
544 if s1s$ = ps$(l) then goto 545 :rem same word
545 gp$(l,ix) = ps$(cc)
549 ix = ix + 1
555 rem SKIP
557 next cc
559 next l
560 gosub 10000 : return
588 rem I highly recommend running this in warp mode to get
589 rem feel for the game, because it could be really slow.
590 rem You can speed it up, however, by not having a status indicator.
592 rem Near the end are guides for developers
593 rem and users. This is our main subroutine.
594 rem It will provide the user with helpful prompts
595 rem and take input from the user regarding how many words, and
596 rem what words to use.
598 rem The global variable "ma" is tracked as the length of the
599 rem longest word. sz is the number of words we play with.
600 restore : ma = 0 : print "How many words do you want?"
601 print "(not too many, or too long please)"
602 print "(we recommend that you put less than 12 words"
603 print "of lengths of 7 characters or below)"
604 input "How many words"; in$ : print "" : print "" : print ""
605 print "Note: spaces and periods are removed from the ends of words."
606 print "This is a good game for children."
607 print "You can only have one of each word."
608 print "Words aren't confirmed as real words."
609 print "So please enter real words to play with them."
610 print "However, we also have default words. To let ";
611 print "the computer finish filling the list, ";
612 print "just enter .... . Enter ... to finish early."
613 ip = val(in$) : if ip <= 0 then goto 8 : rem 0 words
614 dim pr$(ip-1) : sz = 0
615 for i = 0 to ip-1
616 input "Next word"; ii$ : rem Buggy emulator shows "?" regardless
617 ln = len(ii$): if ln > ma then ma = ln:rem update mx wrd lngth
619 if ii$ = "..." then if i = 0 then goto 8 : rem 0 words
620 if ii$ = "..." then sz = -1 : if ii$ = "..." then goto 635
621 if ii$ = "...." then if ip = 1 then goto 900
622 if ii$ = "...." then goto 628 : rem fill with default
623 gosub 2000
624 if cn = 1 then print "that word was already added"
625 if cn = 1 then goto 616 : rem: get the word again
626 gosub 9000 : pr$(i) = ii$ : sz = i
627 next i
628 if i >= ip-1 then goto 635
629 for j = i to ip-1 :rem: fill in the data
630 read ii$ : if ii$ = "..." then goto 1200
631 gosub 2000
632 if cn = 1 then goto 629
633 pr$(j) = ii$ : sz = j
634 next j
635 gosub 890 : rj = 0 : pa = 0 : dim re$(ip-1) : dim pl$(ip-1)
639 print "" : print "" : print ""
640 print "Would you like to have a status indicator? (y/n)"
645 print "Note that it slows you down considerably."
647 input ""; ii$
649 if ii$ = "n" then uu = 1 : if ii$ = "n" then goto 670
650 if ii$ = "y" then uu = 0 : if ii$ = "y" then goto 670
660 rem else
665 print "You must enter y or n. y is Yes and n is No."
668 goto 647
670 rem
671 print "Please wait. The game is loading..."
672 print "In some cases this could take a few minutes..." :
693 print "" : print "" : if ip = 1 then goto 910
694 gosub 4000 : gosub 301 : gosub 535
695 gosub 1500
696 gosub 6500
697 gosub 7000
698 gosub 1000
699 rem go
701 print "" : print "" : print ""
702 print "*********************"
703 print "***WORDSEARCH GAME***"
704 print "*********************"
710 gosub 5000 :rem: print
711 gosub 6600 :rem: the key array and answer list.
790 end
888 rem Turn pr$() into ps$() where the size is the number
889 rem of words (in case they terminate early with "...").
890 if sz = -1 then gosub 1300
891 dim ps$(sz)
892 for i = 0 to sz
893 ps$(i) = pr$(i)
894 next i
896 ip = sz+1
897 rem to make work with "ip-1" elsewhere
898 return
900 dim ps$(0)
901 ps$(0) = "rat"
902 rj = 0 : pa = 0 : dim re$(ip-1) : dim pl$(ip-1)
903 goto 910
906 rem This subroutine continues the running of the game
907 rem normally, except it deals with the case where
908 rem there is only one word. The normal code fails
909 rem in this case (which is why we need 910).
910 gosub 4000
911 gosub 6500
912 dr$ = ps$(0)
913 gosub 949
914 gosub 1001
931 print "" : print "" : print ""
932 print "*********************"
933 print "***WORDSEARCH GAME***"
934 print "*********************"
935 gosub 5000 : rem print the actual game
936 gosub 6600 : rem the key array
940 end
947 rem This subroutine places one word randomly on the board.
948 if ps$(0) = "" then goto 8 : rem (the case with only one word)
949 if len(ps$(0)) > sh then goto 981
950 gosub 49 : me = mr : dr$ = ps$(0)
951 if me = 0 then goto 960 : rem vertical
952 rem here is the code for horizontal
953 mn = 0
954 mx = a-len(dr$)
955 gosub 40 : x = mr
956 mn = 0
957 mx = a-1
958 gosub 40 : y = mr
959 goto 979
960 rem here is our code for vertical
962 mn = 0
963 mx = a-len(dr$)
964 gosub 40 : y = mr
965 mn = 0
967 mx = a-1
968 gosub 40 : x = mr
969 goto 979
979 gosub 6000 : pl$(0) = dr$
980 gosub 10000 : return
981 re$(0) = ps$(0)
982 return
998 rem This subroutine fills the board with random
999 rem characters, assuming that words have already been
1000 rem placed. It copies wo$() to wr$(), then replaces the dots.
1001 for i = 0 to a-1
1002 for j = 0 to a-1
1003 wr$(i,j) = wo$(i,j)
1007 next j
1008 next i
1009 for i = 0 to a-1
1010 for j = 0 to a-1
1012 if wr$(i,j) <> "." then goto 1020
1014 mn = 65: mx = 90
1015 gosub 500
1016 wr$(i,j) = chr$(mr)
1020 next j
1021 next i
1100 gosub 10000 : return
1197 rem This is a helper that will, in the read data loop,
1198 rem use the early termination functionality to avoid crashes.
1199 rem It is here to avoid clutter with ":" commands in main.
1200 sz = -1
1201 if pr$(0) = "..." then goto 8
1202 goto 635
1299 rem Finds our sz; fixes a bug using "...".
1300 sz = 0
1301 for po = 0 to ip-1
1302 if pr$(po) <> "" then sz = po
1303 next po
1304 return
1500 rem This subroutines orders words into an array
1501 rem called fd$(). It orders them in a way such
1502 rem that words next to each other will have an
1503 rem intersection if that is possible. Otherwise,
1504 rem they may not.
1505 rem It makes use of our previous 2D array gp$() to do this.
1510 dim fd$(ip-1) : rem list of words in order we place them
1511 fd$(0) = ps$(0)
1520 for k = 1 to ip-1
1521 st$ = fd$(k-1)
1522 gosub 3500
1523 f = 0 :rem number of words in this subarray
1524 for kc = 0 to ip-1
1525 if gp$(ni,f) = "" then goto 1528
1526 f = kc
1527 next kc
1528 rem now we will find a matching word that is new
1529 for d = 0 to f-1
1530 ii$ = gp$(ni,d) : rem dst word that is matching
1531 gosub 1700 :rem cn = whether it was contained
1532 if cn = 0 then fd$(k) = ii$
1533 if cn = 0 then goto 1649
1534 next d :rem check next subarray item
1535 rem at this point we need an entirely new word
1536 for d = 0 to ip-1
1537 ii$ = ps$(d)
1560 gosub 1700
1570 if cn = 0 then fd$(k) = ii$
1580 if cn = 0 then goto 1649
1590 rem else (haven't found it yet)
1600 next d
1610 rem this should work and is deterministic
1611 rem
1649 next k
1650 gosub 10000 : return
1700 rem Assumes fd$() and ii$ and ip exist. Returns cn.
1701 rem Checks whether ii$ is in fd$(), with 0 as no, and 1 as yes.
1702 cn = 0
1703 for l = 0 to ip-1
1704 if cn = 1 then gosub 10000 : return
1705 if fd$(l) = ii$ then cn = 1
1706 next l
1707 gosub 10000 : return
2000 rem Assumes pr$() and ii$ an ip exist. Outputs cn.
2001 rem returns whether ii$ is in pr$() (0 for no, 1 for yes).
2002 cn = 0
2003 for l = 0 to ip-1
2004 if cn = 1 then gosub 10000 : return
2005 if pr$(l) = ii$ then cn = 1
2006 next l
2007 return
3500 rem Finds the index, outputted as ni, at which st$ is in ps$
3501 rem If it is not present, then it returns -1.
3505 for l = 0 to ip - 1
3510 ni = l
3515 if ps$(ni) = st$ then gosub 10000 : return
3520 next l
3525 ni = -1
3530 gosub 10000 : return
3999 rem Set the board dimensions.
4000 sh = 21: if ma > sh then ma = sh : rem sh = screen height
4001 a = int(ma + ip/5+ ip/8 + ip/10 + ip/20): if a < 3 then a = 3
4002 rem This is an emperically determined subroutine.
4003 if a < ma+1 then a = ma+1
4005 if a > sh then a = sh
4006 dim wr$(a-1,a-1): dim wo$(a-1,a-1) : rem square grid
4007 gosub 10000 : return
4998 rem This subroutine prints the regular game
4999 rem board to the screen.
5000 rem
5001 for i = 0 to a-1
5002 for j = 0 to a-1 : rem now that it is a by a cant use b :P
5003 print wr$(i,j);
5004 next j
5005 print ""
5006 next i
5007 return
6000 rem This subroutine places a word, dr$, on the board & key
6002 rem at wr$/wo$(y,x). me is 1 for horizontal, 0 for vertical.
6003 rem It assumes that this is possible.
6004 for l = 0 to len(dr$)-1
6005 st$ = dr$
6006 le = l
6007 ri = l+1
6008 gosub 40
6009 wr$(y,x) = sr$: wo$(y,x) = sr$
6010 if me = 1 then x = x + 1
6011 if me = 0 then y = y + 1
6012 next l
6013 gosub 10000 : return
6497 rem This little subroutine fills the key board
6498 rem with dots, on top of which words will later be
6499 rem placed. It makes the game more usable.
6500 for po = 0 to a-1
6520 for pp = 0 to a-1
6530 wo$(po,pp) = "."
6540 next pp
6550 next po
6560 gosub 10000 : return
6567 rem This simple subroutine waits for any key to be
6578 rem pressed, and waits in the meantime.
6569 print "Press Any Key To Continue..." : rem ANY KEY
6570 get tm$ : if tm$ = "" then goto 6570
6571 return
6596 rem This subroutine prints out the words
6597 rem that were used and the words that were rejected.
6598 rem It prints the key out last, in case the user wants to search
6599 rem for a word they didn't realize was there once they see
6600 rem the list. (Some people are like that...)
6605 print "To check your answers, "
6611 gosub 6569
6612 print "Words:"
6613 for i = 0 to ip - 1
6614 print pl$(i); : print " ";
6615 next i
6616 print "": gosub 6569
6617 print "Rejected words:"
6618 for i = 0 to ip-1
6619 print re$(i); : print " ";
6620 next i
6621 print "" : gosub 6569 : print "Key:" : print ""
6640 for kl = 0 to a-1
6641 for lk = 0 to a-1
6642 print wo$(kl,lk);
6643 next lk
6644 print ""
6645 next kl
6646 gosub 6569 : print "*********************"
6647 return
6995 rem This subroutine is our smart placing subroutine.
6996 rem Its goal is to place words from fd$() in a way
6997 rem to maximize intersections of words and create
6998 rem the best possible game.
6999 rem Assumes we have fd$(), wo$() and wr$() all ready
7000 id = 0 : rem the initial word spot on the array
7003 if ip = 3 then goto 7500 : rem this somehow fixes a bug
7004 rem above is due to really bad emulator bug, nonsensical
7005 if id > ip-1 then return : rem we have placed all words
7006 if id = ip-1 then goto 7900 : rem 1 word
7010 rem else
7011 goto 7300
7200 rem This is the general smart placer
7300 se$ = fd$(id+1) : si$ = fd$(id)
7310 s0$ = si$ : s1$ = se$ : gosub 55 : fr = 0 : rf = 0
7311 if s2$ = "" then goto 7450
7315 le = 0 : ri = 1 : st$ = s2$ : gosub 40 : tm$ = sr$
7320 for pi = 0 to len(si$)-1
7325 le = pi : ri = pi+1 : st$ = si$ : gosub 40
7330 if sr$ = tm$ then goto 7350
7335 fr = fr + 1
7340 next pi
7350 for po = 0 to len(se$)-1
7355 le = po : ri = po+1 : st$ = se$ : gosub 40
7360 if sr$ = tm$ then goto 7375
7365 rf = rf + 1
7370 next po
7375 rem rf : si$ ;;;;; fr : se$
7380 rem
7385 mf = 1 : mk = 0 : rem 1st word is horizontal, second is vertical
7395 for xx = 0 to a-len(si$)
7400 for yy = rf to a-len(se$)+rf
7401 x = xx : y = yy : dr$ = si$
7402 if xx < 0 then goto 7430
7403 if xx > a-1 then 7430
7404 if yy < 0 then 7428
7405 if yy > a-1 then 7428
7407 kd = mf
7408 gosub 8300
7410 if kk = 0 then goto 7428
7412 x = xx + fr : y = yy - rf
7413 dr$ = se$ : kd = mk
7414 gosub 8300
7415 if kk = 0 then goto 7428
7417 dr$ = si$ : x = xx : y = yy : me = mf : gosub 6000
7420 dr$ = se$ : x = xx + fr : y = yy - rf : me = mk : gosub 6000
7425 pl$(pa) = si$ : pa = pa + 1 : pl$(pa) = se$ : pa = pa + 1
7426 goto 7461
7428 next yy
7430 next xx
7450 dr$ = si$ : gosub 8000
7460 dr$ = se$ : gosub 8000
7461 id = id + 2
7470 goto 7005
7500 dr$ = fd$(0) : gosub 8000
7501 dr$ = fd$(1) : gosub 8000
7502 dr$ = fd$(2) : gosub 8000
7503 return
7900 rem This places the last word
7901 dr$ = fd$(ip-1)
7902 gosub 8000
7926 return
7990 rem This subroutine tries to place a word called dr$
7991 rem anywhere possible on the board by testing
7992 rem all locations with all directions allowed in the game.
8000 rem It is meant for words not placed by our smart placer.
8002 if len(dr$) > sh then goto 8028
8003 for pn = 0 to a-1
8004 for pk = 0 to a-1
8006 kd = 1
8008 gosub 8300
8010 if kk = 1 then gosub 8100 : rem place
8012 if kk = 1 then gosub 10000 : return
8014 rem else (if kk = 0)
8016 kd = 0
8018 gosub 8300
8020 if kk = 1 then gosub 8100 : rem place
8022 if kk = 1 then gosub 10000 : return
8024 next pk
8026 next pn
8028 kk = 0 : re$(rj) = dr$ : rj = rj + 1 : rem add to rejects
8030 gosub 10000 : return
8099 rem This is a parameter converter from 8000 to 6000.
8100 rem It will place dr$ at pn, pk (format (y,x)).
8101 y = pn : x = pk: me = kd: gosub 6000
8102 pl$(pa) = dr$ : pa = pa + 1
8103 gosub 10000 : return
8260 rem this subroutine will check whether
8261 rem we can place a string called dr$
8262 rem in direction kd (0 is vertical, 1 is horizontal)
8263 rem at the position
8264 rem pn, pk (coords as (y,x))
8300 rem returns kk whther we can place
8301 rem (kk = 0 if we can't, = 1 if we can)
8303 lu = len(dr$)
8305 if kd = 1 then goto 8350 : rem horizontal
8307 kk = 1 : rem vertical
8309 if pn+lu-1 > a-1 then kk = 0
8310 for pc = pn to pn+lu-1
8312 le = pc-pn
8313 ri = le+1 : st$ = dr$
8314 gosub 40 : lc$ = sr$
8315 if wo$(pc,pk) <> "." then kk = 0
8316 if wo$(pc,pk) = lc$ then kk = 1
8317 if kk = 0 then gosub 10000 : return
8318 next pc
8319 gosub 10000 : return
8350 kk = 1
8351 if pk+lu-1 > a-1 then kk = 0
8352 if kk = 0 then gosub 10000 : return
8353 for pc = pk to pk+lu-1
8362 le = pc-pk
8363 ri = le+1 : st$ = dr$
8364 gosub 40 : lc$ = sr$
8374 if wo$(pn,pc) <> "." then kk = 0
8376 if wo$(pc,pk) = lc$ then kk = 1
8384 if kk = 0 then gosub 10000 : return
8388 next pc
8389 gosub 10000 : return
8999 rem This subroutine takes in string ii$ and removes the spaces
9000 rem from the end. It is meant to avoid disastrous user errors.
9008 goto 9010
9010 st$ = ii$
9015 tm$ = ""
9020 for ck = 0 to len(ii$)-1
9030 le = ck
9033 ri = ck+1
9035 gosub 40
9050 if sr$ = "" then goto 9200
9100 tm$ = tm$ + sr$
9200 next ck
9300 ii$ = tm$
9301 return
10000 if uu = 1 then return : rem Set uu to 0 on line 1 to not status indicate.
10001 rem This is our rudimentary status indicator
10002 rem function. It will print "." to the indicator line and delete it.
10005 print ".";
10006 for sz=0 to 50 : print ""; : next sz
10007 print chr$(20); : rem this deletes
10008 rem This function is called when stuff happens;
10009 rem that does not mean that it is called consistently, but
10010 rem instead it means that this function will be called
10011 rem as long as the system is not frozen/crashed. So it
10012 rem may take a while for the dot to appear, but if they do, wait.
10013 return
11001 rem Note I can use the same spot because its a comment.
11002 rem Welcome to the function/method guide!
11003 rem Functions will be written like this:
11004 rem <line number>(<arg 1>, <arg 2> , <...>): <quick description>=<output>
11005 rem Longer descriptions can be found at the functions themselves.
11006 rem Also, some functions are called at slightly earlier or later
11007 rem line numbers due to comments. They are still the same function.
11008 rem Some modules are not functions, but just extensions of other functions
11009 rem for readability. These are also here and clearly labeled as not being
11010 rem independent functions for the purposes of clearness.
11011 rem 10 DATA
11012 rem 40 (le, ri, st$): substring function = sr$
11013 rem 49 (none): toincoss function = mr
11014 rem 55 (s0$, s1$): intersection = s2$
11015 rem 100 (mn,mx): random float = mr
11016 rem 300 (ps$()): scrambles ps$() = none
11017 rem 500 (mn,mx): random int = mr
11018 rem 505 (ps$()): grouping finder = gp$()()
11019 rem 600 (none): main = none (the game)
11020 rem 890 (pr$()): creates ps$() = ps$()
11021 rem 900 CONTINUATION OF 600 (single word case)
11022 rem 948 CONTINUATION OF 900 (places one single word randomly)
11023 rem 1000 (wo$()(), wr$()()): fill the board = none
11024 rem 1200 EXTENSION OF 600
11025 rem 1300 (pr$()): helper counter for pr$() > ps$() = sz
11026 rem 1500 (ps$(), gp$()()): fd$() generator = fd$()
11027 rem 1700 (ii$, fd$()): fd$() contains = cn
11028 rem 2000 (ii$, pr$()): pr$() contains = cn
11029 rem 3500 (ps$(), st$): 1500 helper for finding index of value = ni
11030 rem 4000 (ma, ip): board dimensions = wo$()(), wr$()()
11031 rem 5000 (wr$()()): print the game = none
11032 rem 6000 (dr$, me, wo$()(), wr$()()): places a word = none
11033 rem 6500 (wo$()()): fill the key with dots = none
11034 rem 6569 (none): press and key = none
11035 rem 6596 (pl$(), re$(), wo$()()): prints out end game info = none
11036 rem 7000 (fd$(), wo$(), wr$()): smart placer = none
11037 rem 8000 (dr$, wo$(), wr$()): dumb placer = none
11038 rem 8100 CONTINUATION OF 8000
11039 rem 8300 (dr$, y, x, wo$(), wr$()): check if we can place = kk
11040 rem 9000 (ii$): removes end spaces (rstrip) = ii$
11041 rem 10000 (none): Status indicator = none
11101 rem ---Below is a simple guide to the game's inner workings---
11102 rem This is a simple word search game ideal for children and
11103 rem other such individuals. It runs very slowly, and scales
11104 rem badly with both space and time (though, it should scale worse
11105 rem with time, than with space relative to word size and number of
11106 rem words since it has at most two dimensional arrays). To play
11107 rem the game to maximum enjoyment, I recommend warp mode, then
11108 rem normal mode if you want to get some time to dash to manzanita
11109 rem and grab a cup of coffee in the morning (or something).
11110 rem Luckily it has a rough status indicator. If it fills the
11111 rem entirety of the screen do not be afraid, its just being called
11112 rem a lot because it is basically called any time anything at all
11113 rem happens, and a lot is happening.
11114 rem The game works as follows: it will find all combinations of words
11115 rem which can work, and then it will group the words into an order
11116 rem to be placed in, which is based on which words are best grouped
11117 rem with each other (though, it randomly chooses if two words both
11118 rem can be grouped with the same word, leading to different outcomes
11119 rem for the game; note that while some code may look purely
11120 rem deterministic, due to the fact that the entire array ps$() from which
11121 rem the input array pr$() was loaded, it is not since ps$() was scrambled
11122 rem randomly, meaning that any order may be found, and due to the inner
11123 rem workings of the combination finder, it will order the combinations
11124 rem in different ways; this is why every single possible combination of
11125 rem words is technically possible in this game). After loading the
11126 rem placement order list (fd$()), it will place in pairs that will form
11127 rem crosses. It will always make the first word horizontal and the second
11128 rem vertical, but due to the initial scramble, every single possibility
11129 rem can technically occur (thought it typically makes the game less
11130 rem "random"). If a pair can't form a cross (since it either has none
11131 rem of the same letters, or it can't fit it in, it will try to fit each
11132 rem word individually. If that fails, then it will add the word to
11133 rem the rejects list (placed words are added to a placed words list).
11134 rem After each word is placed or rejected, the game is printed, and
11135 rem after the player desires to see the solution it shows first the
11136 rem words, then the rejects, then the answer key. The key is last, in
11137 rem case players see words they want to now find, and don't want to
11138 rem have the key be revealed just yet.
11139 rem
11140 rem Crash Notes:
11141 rem Crashes after:
11142 rem Many, many big words (ie if you put 30+ words of length
11143 rem 12+ it will probably take forever, and might run out of memory).
11144 rem I have run it with 50 words of average length 4 and it actually works
11145 rem fine, just really slowly; remember you can speed up with uu = 1.
11146 rem It tanks especially if you add long words because
11147 rem that is the main factor of grid size.
11148 rem
11149 rem Note: "l" as an iterator is always the letter, not the number.
11150 rem (I know it can look confusing).
11154 rem
11155 rem Side note for users: if you put in tens or
11156 rem hundreds of words as the numbers and terminate early, you still
11157 rem allocate an array of that size; this will crash the game. Also,
11158 rem if you ever get suspicious crashes (ie out of memory with 5 words)
11159 rem try restarting or reloading. The emulator is buggy too. Other
11160 rem successful options to fix emulator bugs include printing items
11161 rem in random places and then deleting the print statements. It's
11162 rem nonsensical, but it worked for me.
11168 rem
11169 rem Empty strings as "words" can break the game on occasion.
11170 rem This is not dealt with because users entering empty strings
11171 rem as words are clearly not planning on playing a legitimate game
11172 rem so it does not matter for the general populace.
11173 rem
11174 rem Good Luck!
11175 rem Thank you for playing!
The problem is not with line 45, despite your ?OUT OF MEMORY AT LINE 45 error. That line in and of itself cannot trigger OOM, since it is merely incrementing a memory variable that would at worst trigger ?OVERFLOW eventually.
The problem is that your BASIC program is now sufficiently large that the PET cannot allocate enough memory for your runtime variables - which is why it was working until you added that last routine.
So: either optimise your memory usage (by trimming/optimising the code and/or refining variable use) or reconfigure xPET for more RAM at startup.
I tried to optimize your code a litte bit.
What I've done:
used CBM Program studio to edit the program listing. A useful feature of this IDE is smart comments. They can be seen only in the editor and removed from actual program listing. I've changed longer comments as smart comments.
Combined shorter lines using ':' operator
$in variable used only once. I have changed alll $ii varibles to
$in
Status indicator routine is simplified and moved to 1000. (If I recall correctly subroutines with shorter line numbers will work faster.)
Reduced the number of status indicator calls.
I have tested the resulting code and it is working up to 17 words in PET 8032 with 32K
1 rem This is a simple wordsearch game generator
2 rem that takes words and creates a board and key from it.
3 rem Words can only be read/written top to bottom or left to right.
4 rem The board is a square between 3x3 and 21x21.
6 uu = 1 : goto 600 : rem (toggle indicator on)
8 print "Zero Words, terminating game..." : rem This small piece
9 end : rem of code here is what happens if you put 0 for the number of words.
10 rem Below is the default data (it's random). Hopefully it is enough.
11 data "rat","clam","ten","sip","lie","ugly","not","yet","thou","if"
12 data "dog","cat","no","yes","maybe","truck","car","trap","lamb"
13 data "three","long","short","two","one","zero","cow","cart","house"
14 data "hair","hall","heart","head","who","is","truth","false","cake"
15 data "five","six","seven","eight","nine","ten","good","bad","rad"
16 data "thy","art","short","long","potatoes","tomato","ramble"
17 data "crumble","shambles","lion","turtle","beach","breach"
18 data "data","read","bamboozle","words","list","assasin","off"
19 data "are","viking","knight","sword","random","treacherous","..."
21 rem If it is not enough data, the game will reach the "..." and
22 rem your game will be cut short (have less words).
40 rem This is substring from le to ri where st$ goes from 0 to len-1
41 rem Left is inclusive and right is not inclusive.
42 rem Assumes that st$ exists; returns sr$. le and ri must also exit.
43 rem This encapsulates the mid function for ease of use.
45 le = le+1: rem: remember basic strings go from 1 to len
46 sr$ = mid$(st$,le,ri-le+1)
47 le = le-1: rem: we try to avoid outside effects
48 return
50 rem: A subroutine that returns a random Boolean (tosses a coin).
51 rem: It will return 0 or 1 randomly; output is in mr.
52 mn = 0: mx = 1
53 gosub 500
54 gosub 100 : return
55 rem Assumes strings named s0$ and s1$ exist.
56 rem (these are the strings we search for an intersection)
57 s2$ = "": rem returns a string of the intersections in s2$.
58 for i = 0 to len(s0$)-1 : rem: for all characters in s0$
59 st$ = s0$: le = i : ri = i+1
60 gosub 40
61 ch$ = sr$ : rem temp var
62 for j = 0 to len(s1$)-1
63 le = j: ri = j+1: st$ = s1$
64 gosub 40
65 if ch$ = sr$ then s2$ = s2$ + ch$
66 next j : next i
68 gosub 100 : return
99 rem Status Indicator
100 if uu=0 then return
110 on uu goto 120,130
120 print "."; : uu=2 :return
130 print chr$(20); : uu=1 :return
300 rem Scrambles the order of ps$().
310 for i = 0 to ip-1
320 mx=ip-1 : mn=0 : gosub 500
330 sp$ = ps$(mr) : ps$(mr) = ps$(i) : ps$(i) = sp$
350 next i
360 gosub 100 : return
499 rem Random Integer subroutine.
500 mr = rnd(0)*(mx+1-mn)+mn : rem Gets a random float.
502 mr = int(mr) : rem we turn it into an integer via truncation
504 return
530 rem This subroutine returns gp$(), a two
531 rem dimensional array of all the words where
532 rem for each value of ps$() where a word is
533 rem the list in gp$() of that value has the words
534 rem that match/intersect with it.
535 dim gp$(ip-1,ip-1)
536 for l=0 to ip-1 : ix=0 : for cc=0 to ip-1
539 s0$=ps$(l) : s1$=ps$(cc)
541 gosub 55
543 if s2$ = "" then goto 545
544 if s1s$ = ps$(l) then goto 545 :rem same word
545 gp$(l,ix) = ps$(cc)
549 ix = ix + 1
557 next cc : next l
560 gosub 100 : return
!-=======================================================================
!-I highly recommend running this in warp mode to get feel for the game
!-because it could be really slow. You can speed it up, however, by not
!-having a status indicator. Near the end are guides for developers and
!-users. This is our main subroutine. It will provide the user with
!- helpful prompts
!-and take input from the user regarding how many words, and what words
!-to use. The global variable "ma" is tracked as the length of the
!-longest word. sz is the number of words we play with.
!-=======================================================================
599 rem main subroutine
600 restore : ma = 0 : print "How many words do you want?"
601 print "(not too many, or too long please)"
602 print "(we recommend that you put less than 12 words"
603 print "of lengths of 7 characters or below)"
604 input "How many words"; in$ : print "" : print "" : print ""
605 print "Note: spaces and periods are removed from the ends of words."
606 print "This is a good game for children."
607 print "You can only have one of each word."
608 print "Words aren't confirmed as real words."
609 print "So please enter real words to play with them."
610 print "However, we also have default words. To let ";
611 print "the computer finish filling the list, ";
612 print "just enter .... . Enter ... to finish early."
613 ip = val(in$) : if ip <= 0 then goto 8 : rem 0 words
614 dim pr$(ip-1) : sz = 0
615 for i = 0 to ip-1
616 input "Next word"; in$
617 ln = len(in$): if ln > ma then ma = ln:rem update mx wrd lngth
619 if in$ = "..." then if i = 0 then goto 8 : rem 0 words
620 if in$ = "..." then sz = -1 : if in$ = "..." then goto 635
621 if in$ = "...." then if ip = 1 then goto 900
622 if in$ = "...." then goto 628 : rem fill with default
623 gosub 2000
624 if cn = 1 then print "that word was already added"
625 if cn = 1 then goto 616 : rem: get the word again
626 gosub 9000 : pr$(i) = in$ : sz = i
627 next i
628 if i >= ip-1 then goto 635
629 for j = i to ip-1 :rem: fill in the data
630 read in$ : if in$ = "..." then goto 1200
631 gosub 2000
632 if cn = 1 then goto 629
633 pr$(j) = in$ : sz = j
634 next j
635 gosub 890 : rj = 0 : pa = 0 : dim re$(ip-1) : dim pl$(ip-1)
639 print "" : print "" : print ""
640 print "Would you like to have a status indicator? (y/n)"
645 print "Note that it slows you down considerably."
647 input ""; in$
649 if in$ = "n" then uu = 0 : if in$ = "n" then goto 670
650 if in$ = "y" then uu = 1 : if in$ = "y" then goto 670
660 rem else
665 print "You must enter y or n. y is Yes and n is No."
668 goto 647
670 print "Please wait. The game is loading..."
671 print "In some cases this could take a few minutes..." :
693 print "" : print "" : if ip = 1 then goto 910
694 gosub 4000 : gosub 310 : gosub 535
695 gosub 1500
696 gosub 6500
697 gosub 7000
698 gosub 1000
699 rem go
701 print "" : print "" : print ""
702 print "*********************"
703 print "***WORDSEARCH GAME***"
704 print "*********************"
710 gosub 5000 :rem: print
711 gosub 6600 :rem: the key array and answer list.
790 end
888 rem Turn pr$() into ps$() where the size is the number
889 rem of words (in case they terminate early with "...").
890 if sz = -1 then gosub 1300
891 dim ps$(sz)
892 for i = 0 to sz
893 ps$(i) = pr$(i)
894 next i
896 ip = sz+1
897 rem to make work with "ip-1" elsewhere
898 return
900 dim ps$(0)
901 ps$(0) = "rat"
902 rj = 0 : pa = 0 : dim re$(ip-1) : dim pl$(ip-1)
903 goto 910
906 rem This subroutine continues the running of the game
907 rem normally, except it deals with the case where
908 rem there is only one word. The normal code fails
909 rem in this case (which is why we need 910).
910 gosub 4000
911 gosub 6500
912 dr$ = ps$(0)
913 gosub 949
914 gosub 1001
931 print "" : print "" : print ""
932 print "*********************"
933 print "***WORDSEARCH GAME***"
934 print "*********************"
935 gosub 5000 : rem print the actual game
936 gosub 6600 : rem the key array
940 end
947 rem This subroutine places one word randomly on the board.
948 if ps$(0) = "" then goto 8 : rem (the case with only one word)
949 if len(ps$(0)) > sh then goto 981
950 gosub 50 : me = mr : dr$ = ps$(0)
951 if me = 0 then goto 960 : rem vertical
952 rem here is the code for horizontal
953 mn = 0
954 mx = a-len(dr$)
955 gosub 40 : x = mr
956 mn=0 : mx=a-1
958 gosub 40 : y = mr
959 goto 979
960 rem here is our code for vertical
962 mn=0 : mx=a-len(dr$)
964 gosub 40 : y = mr
965 mn=0: mx=a-1
968 gosub 40 : x = mr
969 goto 979
979 gosub 6000 : pl$(0) = dr$
980 gosub 100 : return
981 re$(0) = ps$(0)
982 return
998 rem This subroutine fills the board with random
999 rem characters, assuming that words have already been
1000 rem placed. It copies wo$() to wr$(), then replaces the dots.
1001 for i=0 to a-1 : for j=0 to a-1
1003 wr$(i,j) = wo$(i,j)
1007 next j : next i
1010 for i=0 to a-1 : for j=0 to a-1
1012 if wr$(i,j) <> "." then goto 1020
1014 mn = 65: mx = 90
1015 gosub 500
1016 wr$(i,j) = chr$(mr)
1020 next j : next i
1100 gosub 100 : return
1197 rem This is a helper that will, in the read data loop,
1198 rem use the early termination functionality to avoid crashes.
1199 rem It is here to avoid clutter with ":" commands in main.
1200 sz = -1
1201 if pr$(0) = "..." then goto 8
1202 goto 635
1299 rem Finds our sz; fixes a bug using "...".
1300 sz = 0
1301 for po = 0 to ip-1
1302 if pr$(po) <> "" then sz = po
1303 next po
1304 return
1500 rem This subroutines orders words into an array
1501 rem called fd$(). It orders them in a way such
1502 rem that words next to each other will have an
1503 rem intersection if that is possible. Otherwise,
1504 rem they may not.
1505 rem It makes use of our previous 2D array gp$() to do this.
1510 dim fd$(ip-1) : rem list of words in order we place them
1511 fd$(0) = ps$(0)
1520 for k = 1 to ip-1
1521 st$ = fd$(k-1)
1522 gosub 3500
1523 f = 0 :rem number of words in this subarray
1524 for kc = 0 to ip-1
1525 if gp$(ni,f) = "" then goto 1528
1526 f = kc
1527 next kc
1528 rem now we will find a matching word that is new
1529 for d = 0 to f-1
1530 in$ = gp$(ni,d) : rem dst word that is matching
1531 gosub 1700 :rem cn = whether it was contained
1532 if cn = 0 then fd$(k) = in$
1533 if cn = 0 then goto 1649
1534 next d :rem check next subarray item
1535 rem at this point we need an entirely new word
1536 for d = 0 to ip-1
1537 in$ = ps$(d)
1560 gosub 1700
1570 if cn = 0 then fd$(k) = in$
1580 if cn = 0 then goto 1649
1590 rem else (haven't found it yet)
1600 next d
1610 rem this should work and is deterministic
1611 rem
1649 next k
1650 gosub 100 : return
1700 rem Assumes fd$() and in$ and ip exist. Returns cn.
1701 rem Checks whether in$ is in fd$(), with 0 as no, and 1 as yes.
1702 cn = 0
1703 for l = 0 to ip-1
1704 if cn = 1 then gosub 100 : return
1705 if fd$(l) = in$ then cn = 1
1706 next l
1707 gosub 100 : return
2000 rem Assumes pr$() and in$ an ip exist. Outputs cn.
2001 rem returns whether in$ is in pr$() (0 for no, 1 for yes).
2002 cn = 0
2003 for l = 0 to ip-1
2004 if cn = 1 then gosub 100 : return
2005 if pr$(l) = in$ then cn = 1
2006 next l
2007 return
3500 rem Finds the index, outputted as ni, at which st$ is in ps$
3501 rem If it is not present, then it returns -1.
3505 for l = 0 to ip - 1
3510 ni = l
3515 if ps$(ni) = st$ then gosub 100 : return
3520 next l
3525 ni = -1
3530 gosub 100 : return
3999 rem Set the board dimensions.
4000 sh = 21: if ma > sh then ma = sh : rem sh = screen height
4001 a = int(ma + ip/5+ ip/8 + ip/10 + ip/20): if a < 3 then a = 3
4002 rem This is an emperically determined subroutine.
4003 if a < ma+1 then a = ma+1
4005 if a > sh then a = sh
4006 dim wr$(a-1,a-1): dim wo$(a-1,a-1) : rem square grid
4007 gosub 100 : return
5000 rem Print the regular game board
5001 for i=0 to a-1 : for j=0 to a-1 : rem now that it is a by a cant use b :P
5003 print wr$(i,j);
5004 next j
5005 print ""
5006 next i
5007 return
6000 rem This subroutine places a word, dr$, on the board & key
6002 rem at wr$/wo$(y,x). me is 1 for horizontal, 0 for vertical.
6003 rem It assumes that this is possible.
6004 for l = 0 to len(dr$)-1
6005 st$=dr$ : le=l : ri=l+1
6008 gosub 40
6009 wr$(y,x) = sr$: wo$(y,x) = sr$
6010 if me=1 then x=x + 1
6011 if me=0 then y=y + 1
6012 next l
6013 gosub 100 : return
6497 rem This little subroutine fills the key board
6498 rem with dots, on top of which words will later be
6499 rem placed. It makes the game more usable.
6500 for po=0 to a-1 : for pp=0 to a-1
6530 wo$(po,pp) = "."
6540 next pp : next po
6560 gosub 100 : return
6568 rem Waits for any key to be pressed
6569 print "Press Any Key To Continue..." : rem ANY KEY
6570 get tm$ : if tm$ = "" then goto 6570
6571 return
6596 rem This subroutine prints out the words
6597 rem that were used and the words that were rejected.
6598 rem It prints the key out last, in case the user wants to search
6599 rem for a word they didn't realize was there once they see
6600 rem the list. (Some people are like that...)
6605 print "To check your answers, "
6611 gosub 6569
6612 print "Words:"
6613 for i = 0 to ip - 1
6614 print pl$(i); : print " ";
6615 next i
6616 print "": gosub 6569
6617 print "Rejected words:"
6618 for i = 0 to ip-1
6619 print re$(i); : print " ";
6620 next i
6621 print "" : gosub 6569 : print "Key:" : print ""
6640 for kl = 0 to a-1
6641 for lk = 0 to a-1
6642 print wo$(kl,lk);
6643 next lk
6644 print ""
6645 next kl
6646 gosub 6569 : print "*********************"
6647 return
6995 rem This subroutine is our smart placing subroutine.
6996 rem Its goal is to place words from fd$() in a way
6997 rem to maximize intersections of words and create
6998 rem the best possible game.
6999 rem Assumes we have fd$(), wo$() and wr$() all ready
7000 id = 0 : rem the initial word spot on the array
7003 if ip = 3 then goto 7500 : rem this somehow fixes a bug
7004 rem above is due to really bad emulator bug, nonsensical
7005 if id > ip-1 then return : rem we have placed all words
7006 if id = ip-1 then goto 7900 : rem 1 word
7010 rem else
7011 goto 7300
7200 rem This is the general smart placer
7300 se$ = fd$(id+1) : si$ = fd$(id)
7310 s0$ = si$ : s1$ = se$ : gosub 55 : fr = 0 : rf = 0
7311 if s2$ = "" then goto 7450
7315 le = 0 : ri = 1 : st$ = s2$ : gosub 40 : tm$ = sr$
7320 for pi = 0 to len(si$)-1
7325 le = pi : ri = pi+1 : st$ = si$ : gosub 40
7330 if sr$ = tm$ then goto 7350
7335 fr = fr + 1
7340 next pi
7350 for po = 0 to len(se$)-1
7355 le = po : ri = po+1 : st$ = se$ : gosub 40
7360 if sr$ = tm$ then goto 7385
7365 rf = rf + 1
7370 next po
7385 mf = 1 : mk = 0 : rem 1st word is horizontal, second is vertical
7395 for xx = 0 to a-len(si$)
7400 for yy = rf to a-len(se$)+rf
7401 x = xx : y = yy : dr$ = si$
7402 if xx < 0 then goto 7430
7403 if xx > a-1 then 7430
7404 if yy < 0 then 7428
7405 if yy > a-1 then 7428
7407 kd = mf
7408 gosub 8300
7410 if kk = 0 then goto 7428
7412 x = xx + fr : y = yy - rf
7413 dr$ = se$ : kd = mk
7414 gosub 8300
7415 if kk = 0 then goto 7428
7417 dr$ = si$ : x = xx : y = yy : me = mf : gosub 6000
7420 dr$ = se$ : x = xx + fr : y = yy - rf : me = mk : gosub 6000
7425 pl$(pa) = si$ : pa = pa + 1 : pl$(pa) = se$ : pa = pa + 1
7426 goto 7461
7428 next yy
7430 next xx
7450 dr$ = si$ : gosub 8000
7460 dr$ = se$ : gosub 8000
7461 id = id + 2
7470 goto 7005
7500 dr$ = fd$(0) : gosub 8000
7501 dr$ = fd$(1) : gosub 8000
7502 dr$ = fd$(2) : gosub 8000
7503 return
7900 rem This places the last word
7901 dr$ = fd$(ip-1)
7902 gosub 8000
7926 return
7990 rem This subroutine tries to place a word called dr$
7991 rem anywhere possible on the board by testing
7992 rem all locations with all directions allowed in the game.
8000 rem It is meant for words not placed by our smart placer.
8002 if len(dr$) > sh then goto 8028
8003 for pn = 0 to a-1
8004 for pk = 0 to a-1
8006 kd = 1
8008 gosub 8300
8010 if kk = 1 then gosub 8100 : rem place
8012 if kk = 1 then gosub 100 : return
8014 rem else (if kk = 0)
8016 kd = 0
8018 gosub 8300
8020 if kk = 1 then gosub 8100 : rem place
8022 if kk = 1 then gosub 100 : return
8024 next pk
8026 next pn
8028 kk = 0 : re$(rj) = dr$ : rj = rj + 1 : rem add to rejects
8030 gosub 100 : return
8099 rem This is a parameter converter from 8000 to 6000.
8100 rem It will place dr$ at pn, pk (format (y,x)).
8101 y = pn : x = pk: me = kd: gosub 6000
8102 pl$(pa) = dr$ : pa = pa + 1
8103 gosub 100 : return
8260 rem this subroutine will check whether
8261 rem we can place a string called dr$
8262 rem in direction kd (0 is vertical, 1 is horizontal)
8263 rem at the position
8264 rem pn, pk (coords as (y,x))
8300 rem returns kk whther we can place
8301 rem (kk = 0 if we can't, = 1 if we can)
8303 lu = len(dr$)
8305 if kd = 1 then goto 8350 : rem horizontal
8307 kk = 1 : rem vertical
8309 if pn+lu-1 > a-1 then kk = 0
8310 for pc = pn to pn+lu-1
8312 le = pc-pn
8313 ri = le+1 : st$ = dr$
8314 gosub 40 : lc$ = sr$
8315 if wo$(pc,pk) <> "." then kk = 0
8316 if wo$(pc,pk) = lc$ then kk = 1
8317 if kk = 0 then gosub 100 : return
8318 next pc
8319 gosub 100 : return
8350 kk = 1
8351 if pk+lu-1 > a-1 then kk = 0
8352 if kk = 0 then gosub 100 : return
8353 for pc = pk to pk+lu-1
8362 le = pc-pk
8363 ri = le+1 : st$ = dr$
8364 gosub 40 : lc$ = sr$
8374 if wo$(pn,pc) <> "." then kk = 0
8376 if wo$(pc,pk) = lc$ then kk = 1
8384 if kk = 0 then gosub 100 : return
8388 next pc
8389 gosub 100 : return
8999 rem This subroutine takes in string in$ and removes the spaces
9000 rem from the end. It is meant to avoid disastrous user errors.
9008 goto 9010
9010 st$ = in$
9015 tm$ = ""
9020 for ck = 0 to len(in$)-1
9030 le = ck
9033 ri = ck+1
9035 gosub 40
9050 if sr$ = "" then goto 9200
9100 tm$ = tm$ + sr$
9200 next ck
9300 in$ = tm$
9301 return
!-================================================================================
!-11001 rem Note I can use the same spot because its a comment.
!-11002 rem Welcome to the function/method guide!
!-11003 rem Functions will be written like this:
!-11004 rem <line number>(<arg 1>, <arg 2> , <...>): <quick description>=<output>
!-11005 rem Longer descriptions can be found at the functions themselves.
!-11006 rem Also, some functions are called at slightly earlier or later
!-11007 rem line numbers due to comments. They are still the same function.
!-11008 rem Some modules are not functions, but just extensions of other functions
!-11009 rem for readability. These are also here and clearly labeled as not being
!-11010 rem independent functions for the purposes of clearness.
!-11011 rem 10 DATA
!-11012 rem 40 (le, ri, st$): substring function = sr$
!-11013 rem 49 (none): toincoss function = mr
!-11014 rem 55 (s0$, s1$): intersection = s2$
!-11015 rem 100 (mn,mx): random float = mr
!-11016 rem 300 (ps$()): scrambles ps$() = none
!-11017 rem 500 (mn,mx): random int = mr
!-11018 rem 505 (ps$()): grouping finder = gp$()()
!-11019 rem 600 (none): main = none (the game)
!-11020 rem 890 (pr$()): creates ps$() = ps$()
!-11021 rem 900 CONTINUATION OF 600 (single word case)
!-11022 rem 948 CONTINUATION OF 900 (places one single word randomly)
!-11023 rem 1000 (wo$()(), wr$()()): fill the board = none
!-11024 rem 1200 EXTENSION OF 600
!-11025 rem 1300 (pr$()): helper counter for pr$() > ps$() = sz
!-11026 rem 1500 (ps$(), gp$()()): fd$() generator = fd$()
!-11027 rem 1700 (in$, fd$()): fd$() contains = cn
!-11028 rem 2000 (in$, pr$()): pr$() contains = cn
!-11029 rem 3500 (ps$(), st$): 1500 helper for finding index of value = ni
!-11030 rem 4000 (ma, ip): board dimensions = wo$()(), wr$()()
!-11031 rem 5000 (wr$()()): print the game = none
!-11032 rem 6000 (dr$, me, wo$()(), wr$()()): places a word = none
!-11033 rem 6500 (wo$()()): fill the key with dots = none
!-11034 rem 6569 (none): press and key = none
!-11035 rem 6596 (pl$(), re$(), wo$()()): prints out end game info = none
!-11036 rem 7000 (fd$(), wo$(), wr$()): smart placer = none
!-11037 rem 8000 (dr$, wo$(), wr$()): dumb placer = none
!-11038 rem 8100 CONTINUATION OF 8000
!-11039 rem 8300 (dr$, y, x, wo$(), wr$()): check if we can place = kk
!-11040 rem 9000 (in$): removes end spaces (rstrip) = in$
!-11041 rem 10000 (none): Status indicator = none
!-================================================================================
!-Comment
!-================================================================================
!-11101 rem ---Below is a simple guide to the game's inner workings---
!-11102 rem This is a simple word search game ideal for children and
!-11103 rem other such individuals. It runs very slowly, and scales
!-11104 rem badly with both space and time (though, it should scale worse
!-11105 rem with time, than with space relative to word size and number of
!-11106 rem words since it has at most two dimensional arrays). To play
!-11107 rem the game to maximum enjoyment, I recommend warp mode, then
!-11108 rem normal mode if you want to get some time to dash to manzanita
!-11109 rem and grab a cup of coffee in the morning (or something).
!-11110 rem Luckily it has a rough status indicator. If it fills the
!-11111 rem entirety of the screen do not be afraid, its just being called
!-11112 rem a lot because it is basically called any time anything at all
!-11113 rem happens, and a lot is happening.
!-11114 rem The game works as follows: it will find all combinations of words
!-11115 rem which can work, and then it will group the words into an order
!-11116 rem to be placed in, which is based on which words are best grouped
!-11117 rem with each other (though, it randomly chooses if two words both
!-11118 rem can be grouped with the same word, leading to different outcomes
!-11119 rem for the game; note that while some code may look purely
!-11120 rem deterministic, due to the fact that the entire array ps$() from which
!-11121 rem the input array pr$() was loaded, it is not since ps$() was scrambled
!-11122 rem randomly, meaning that any order may be found, and due to the inner
!-11123 rem workings of the combination finder, it will order the combinations
!-11124 rem in different ways; this is why every single possible combination of
!-11125 rem words is technically possible in this game). After loading the
!-11126 rem placement order list (fd$()), it will place in pairs that will form
!-11127 rem crosses. It will always make the first word horizontal and the second
!-11128 rem vertical, but due to the initial scramble, every single possibility
!-11129 rem can technically occur (thought it typically makes the game less
!-11130 rem "random"). If a pair can't form a cross (since it either has none
!-11131 rem of the same letters, or it can't fit it in, it will try to fit each
!-11132 rem word individually. If that fails, then it will add the word to
!-11133 rem the rejects list (placed words are added to a placed words list).
!-11134 rem After each word is placed or rejected, the game is printed, and
!-11135 rem after the player desires to see the solution it shows first the
!-11136 rem words, then the rejects, then the answer key. The key is last, in
!-11137 rem case players see words they want to now find, and don't want to
!-11138 rem have the key be revealed just yet.
!-11139 rem
!-11140 rem Crash Notes:
!-11141 rem Crashes after:
!-11142 rem Many, many big words (ie if you put 30+ words of length
!-11143 rem 12+ it will probably take forever, and might run out of memory).
!-11144 rem I have run it with 50 words of average length 4 and it actually works
!-11145 rem fine, just really slowly; remember you can speed up with uu = 1.
!-11146 rem It tanks especially if you add long words because
!-11147 rem that is the main factor of grid size.
!-11148 rem
!-11149 rem Note: "l" as an iterator is always the letter, not the number.
!-11150 rem (I know it can look confusing).
!-11154 rem
!-11155 rem Side note for users: if you put in tens or
!-11156 rem hundreds of words as the numbers and terminate EARLY, you still
!-11157 rem allocate an array of that size; this will crash the game. Also,
!-11158 rem if you ever get suspicious crashes (ie out of memory with 5 words)
!-11159 rem try restarting or reloading. The emulator is buggy too. Other
!-11160 rem successful options to fix emulator bugs include printing items
!-11161 rem in random places and then deleting the print statements. It's
!-11162 rem nonsensical, but it worked for me.
!-11168 rem
!-11169 rem Empty strings as "words" can break the game on occasion.
!-11170 rem This is not dealt with because users entering empty strings
!-11171 rem as words are clearly not planning on playing a legitimate game
!-11172 rem so it does not matter for the general populace.
!-11173 rem
!-11174 rem Good Luck!
!-11175 rem Thank you for playing!
!-================================================================================
In fact, the error is very simple !
The error comes from the lines:
gosub 10000 : return
GOSUB will keep in the stack the return address, so after a few calls, the stack will be full (the stack is 256 bytes on 6502).
The solution is to replace with:
goto 10000

NSInvalidArgumentException crash for iPad Pro Sim but not for other iPad Sim

I have an app in the App Store that I haven't maintained since iOS7's release and getting some requests to refresh it.
I am attempting to get it updated so that it runs on latest iOS 8 and all current iOS iPad devices.
When I test run in sim for any non-Pro iPad simulators, it works. But when I test run on iPad Pro, it crashes. Here are the details.
In main.m:
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// crashes on this line (i know this is not that useful)
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Output window (apologize for the verbosity here, but didn't want to leave out anything potentially useful):
Warning: Error creating LLDB target at path '/Users/pubnubcvconover/Library/Developer/Xcode/DerivedData/Stats-Pad-coxczetuymekypghmygwqysiqulp/Build/Products/Debug-iphonesimulator/Lacrosse-Stats.app'- using an empty LLDB target which can cause slow memory reads from remote devices.
2016-02-28 16:59:43.301 Lacrosse-Stats[4205:95840] ADBannerView:didFailToReceiveAdWithError:The operation couldn’t be completed. (ADErrorDomain error 3.)
2016-02-28 16:59:43.303 Lacrosse-Stats[4205:95840] Ran setTeams
2016-02-28 16:59:44.222 Lacrosse-Stats[4205:95840] CoreData: error: -addPersistentStoreWithType:Binary configuration:(null) URL:file:///Users/pubnubcvconover/Library/Developer/CoreSimulator/Devices/91D7C4F6-34CA-4761-913F-C0B50E753469/data/Containers/Data/Application/ED789ADC-FB9C-43E2-8FDE-E02D80DD43E6/Documents/Stats_Pad.bin options:{
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;
} ... returned error Error Domain=NSCocoaErrorDomain Code=134130 "(null)" UserInfo={URL=file:///Users/pubnubcvconover/Library/Developer/CoreSimulator/Devices/91D7C4F6-34CA-4761-913F-C0B50E753469/data/Containers/Data/Application/ED789ADC-FB9C-43E2-8FDE-E02D80DD43E6/Documents/Stats_Pad.bin, metadata={
NSPersistenceFrameworkVersion = 641;
NSStoreModelVersionHashes = {
"field_conditions" = <1a8f23c4 a8f9f08a 7504bd89 b6c608df 89106202 f9c81f02 2441924c 12245334>;
"field_layout" = <da72d767 8f4c3614 fe56ab18 37905a4e b7890395 03515759 46c20c7b 78cbb6cb>;
game = <8f8c1e3b 595416df 4164209d 35268bfd e4f41bf7 aed776a9 3bcfe86a dea6fe6a>;
gender = <bcdc57c3 7ad84924 40c67207 735167f4 e773c4b8 6fc53316 b9fe0220 4e53fad8>;
levels = <7aa35176 e55edff3 7ac01812 5cc17a05 60013487 92196c1d 366a437b a108a9ef>;
p = <593e105a 8ce080f6 aeb0081d 250039e3 6363b0a0 380fc096 6d18653e da7c1612>;
"p_event" = <acf2f48d 3d5ef365 6e6153a2 268ab4d2 9c4776ed 6165781e f86c0bbc 5b8bfe90>;
"p_type" = <36aaae5d db755d03 9a66e7b0 703ca8bf 5de4210a c6c9e8e3 ea77b8f4 6fd8f8fb>;
penalty = <a8ff8a90 08434fec 24caa525 b16972eb f9a35891 54945888 e68d6faf 7d7aea9f>;
"penalty_event" = <09ef67b3 238a32e0 1a2526d6 82374563 c7275b43 a11d26df fa8447b4 ac7f1175>;
"penalty_type" = <3cdcaf67 0748f85e 0b300ba0 4119f7c2 04cf6a39 1b836ec8 5850f3e6 3662e8ff>;
player = <9d572c6d 15c11f5f 5d4aa3d0 10b75ea3 fa3dd352 1f89a53f f3a3f02e b3d1a4c1>;
position = <89407c79 8f0655a6 550666a3 9e87738d fb985882 5ae70c3a 9ca51fd7 50b24a94>;
roster = <34471eca 339a9ab4 ed86afc9 727c17c3 6117156b e726de09 97c979f2 d4272814>;
rules = <0f7d4bc6 5b82e1ee 6b3e9c3d 2c73ea62 78c6bbbb bb02b6c0 0bdc8a5e 2bc1d22d>;
statistic = <b92a539d 6329e839 d24a80ef e4006a28 3ee3cf68 5cbe1342 5a79f9c7 760f3ffe>;
"statistic_event" = <2d6d03bf 53f05b88 ddc692bc ab805dea 210dc3cb 93ea04e9 c2005fe1 d9f817d3>;
"statistic_type" = <84c5603e 008cdbc3 411c883d a0ac485b 160c35c8 f5ce7394 0fc06d2d c72ece9d>;
team = <97de1350 f685c550 8de940e6 e0c6d8fc f2cd1b80 94725d1b 535f0ff3 13474223>;
"weather_conditions" = <23bce103 1dbe85b6 c7b92d66 69c2d334 34baf747 8ae60dcc dee2b5e0 b739bf31>;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = Binary;
NSStoreUUID = "829124BC-14FB-43C5-A845-A630BB9603E9";
"_NSAutoVacuumLevel" = 2;
}, reason=Can't find model for source store} with userInfo dictionary {
URL = "file:///Users/pubnubcvconover/Library/Developer/CoreSimulator/Devices/91D7C4F6-34CA-4761-913F-C0B50E753469/data/Containers/Data/Application/ED789ADC-FB9C-43E2-8FDE-E02D80DD43E6/Documents/Stats_Pad.bin";
metadata = {
NSPersistenceFrameworkVersion = 641;
NSStoreModelVersionHashes = {
"field_conditions" = <1a8f23c4 a8f9f08a 7504bd89 b6c608df 89106202 f9c81f02 2441924c 12245334>;
"field_layout" = <da72d767 8f4c3614 fe56ab18 37905a4e b7890395 03515759 46c20c7b 78cbb6cb>;
game = <8f8c1e3b 595416df 4164209d 35268bfd e4f41bf7 aed776a9 3bcfe86a dea6fe6a>;
gender = <bcdc57c3 7ad84924 40c67207 735167f4 e773c4b8 6fc53316 b9fe0220 4e53fad8>;
levels = <7aa35176 e55edff3 7ac01812 5cc17a05 60013487 92196c1d 366a437b a108a9ef>;
p = <593e105a 8ce080f6 aeb0081d 250039e3 6363b0a0 380fc096 6d18653e da7c1612>;
"p_event" = <acf2f48d 3d5ef365 6e6153a2 268ab4d2 9c4776ed 6165781e f86c0bbc 5b8bfe90>;
"p_type" = <36aaae5d db755d03 9a66e7b0 703ca8bf 5de4210a c6c9e8e3 ea77b8f4 6fd8f8fb>;
penalty = <a8ff8a90 08434fec 24caa525 b16972eb f9a35891 54945888 e68d6faf 7d7aea9f>;
"penalty_event" = <09ef67b3 238a32e0 1a2526d6 82374563 c7275b43 a11d26df fa8447b4 ac7f1175>;
"penalty_type" = <3cdcaf67 0748f85e 0b300ba0 4119f7c2 04cf6a39 1b836ec8 5850f3e6 3662e8ff>;
player = <9d572c6d 15c11f5f 5d4aa3d0 10b75ea3 fa3dd352 1f89a53f f3a3f02e b3d1a4c1>;
position = <89407c79 8f0655a6 550666a3 9e87738d fb985882 5ae70c3a 9ca51fd7 50b24a94>;
roster = <34471eca 339a9ab4 ed86afc9 727c17c3 6117156b e726de09 97c979f2 d4272814>;
rules = <0f7d4bc6 5b82e1ee 6b3e9c3d 2c73ea62 78c6bbbb bb02b6c0 0bdc8a5e 2bc1d22d>;
statistic = <b92a539d 6329e839 d24a80ef e4006a28 3ee3cf68 5cbe1342 5a79f9c7 760f3ffe>;
"statistic_event" = <2d6d03bf 53f05b88 ddc692bc ab805dea 210dc3cb 93ea04e9 c2005fe1 d9f817d3>;
"statistic_type" = <84c5603e 008cdbc3 411c883d a0ac485b 160c35c8 f5ce7394 0fc06d2d c72ece9d>;
team = <97de1350 f685c550 8de940e6 e0c6d8fc f2cd1b80 94725d1b 535f0ff3 13474223>;
"weather_conditions" = <23bce103 1dbe85b6 c7b92d66 69c2d334 34baf747 8ae60dcc dee2b5e0 b739bf31>;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = Binary;
NSStoreUUID = "829124BC-14FB-43C5-A845-A630BB9603E9";
"_NSAutoVacuumLevel" = 2;
};
reason = "Can't find model for source store";
}
2016-02-28 16:59:44.223 Lacrosse-Stats[4205:95840] CoreData: annotation: NSPersistentStoreCoordinator's current model hashes are {
"field_conditions" = <1a8f23c4 a8f9f08a 7504bd89 b6c608df 89106202 f9c81f02 2441924c 12245334>;
"field_layout" = <da72d767 8f4c3614 fe56ab18 37905a4e b7890395 03515759 46c20c7b 78cbb6cb>;
game = <7c5aa182 4171414b b6bcfb04 358894d8 95dd0b1f b32ba46d 440ac807 17a00b19>;
gender = <bcdc57c3 7ad84924 40c67207 735167f4 e773c4b8 6fc53316 b9fe0220 4e53fad8>;
levels = <7aa35176 e55edff3 7ac01812 5cc17a05 60013487 92196c1d 366a437b a108a9ef>;
p = <593e105a 8ce080f6 aeb0081d 250039e3 6363b0a0 380fc096 6d18653e da7c1612>;
"p_event" = <acf2f48d 3d5ef365 6e6153a2 268ab4d2 9c4776ed 6165781e f86c0bbc 5b8bfe90>;
"p_type" = <36aaae5d db755d03 9a66e7b0 703ca8bf 5de4210a c6c9e8e3 ea77b8f4 6fd8f8fb>;
penalty = <a8ff8a90 08434fec 24caa525 b16972eb f9a35891 54945888 e68d6faf 7d7aea9f>;
"penalty_event" = <09ef67b3 238a32e0 1a2526d6 82374563 c7275b43 a11d26df fa8447b4 ac7f1175>;
"penalty_type" = <3cdcaf67 0748f85e 0b300ba0 4119f7c2 04cf6a39 1b836ec8 5850f3e6 3662e8ff>;
player = <4918d629 1aacc24b 59f5942f 0a0222ea 72edf9c7 18d74c0b ec0de756 5ad19d4a>;
position = <89407c79 8f0655a6 550666a3 9e87738d fb985882 5ae70c3a 9ca51fd7 50b24a94>;
roster = <34471eca 339a9ab4 ed86afc9 727c17c3 6117156b e726de09 97c979f2 d4272814>;
rules = <0f7d4bc6 5b82e1ee 6b3e9c3d 2c73ea62 78c6bbbb bb02b6c0 0bdc8a5e 2bc1d22d>;
statistic = <b92a539d 6329e839 d24a80ef e4006a28 3ee3cf68 5cbe1342 5a79f9c7 760f3ffe>;
"statistic_event" = <f8cecbe6 338d513d fc123e58 0cc3c8c6 15295759 91a7eb52 af6f5603 c26f571a>;
"statistic_type" = <84c5603e 008cdbc3 411c883d a0ac485b 160c35c8 f5ce7394 0fc06d2d c72ece9d>;
team = <214fad10 4519c1a5 e799b6ec aefc9adf 16dcae30 b09a01c6 00c4a89d cb113e16>;
"weather_conditions" = <23bce103 1dbe85b6 c7b92d66 69c2d334 34baf747 8ae60dcc dee2b5e0 b739bf31>;
}
2016-02-28 16:59:44.225 Lacrosse-Stats[4205:95840] Unresolved error Error Domain=NSCocoaErrorDomain Code=134130 "(null)" UserInfo={URL=file:///Users/pubnubcvconover/Library/Developer/CoreSimulator/Devices/91D7C4F6-34CA-4761-913F-C0B50E753469/data/Containers/Data/Application/ED789ADC-FB9C-43E2-8FDE-E02D80DD43E6/Documents/Stats_Pad.bin, metadata={
NSPersistenceFrameworkVersion = 641;
NSStoreModelVersionHashes = {
"field_conditions" = <1a8f23c4 a8f9f08a 7504bd89 b6c608df 89106202 f9c81f02 2441924c 12245334>;
"field_layout" = <da72d767 8f4c3614 fe56ab18 37905a4e b7890395 03515759 46c20c7b 78cbb6cb>;
game = <8f8c1e3b 595416df 4164209d 35268bfd e4f41bf7 aed776a9 3bcfe86a dea6fe6a>;
gender = <bcdc57c3 7ad84924 40c67207 735167f4 e773c4b8 6fc53316 b9fe0220 4e53fad8>;
levels = <7aa35176 e55edff3 7ac01812 5cc17a05 60013487 92196c1d 366a437b a108a9ef>;
p = <593e105a 8ce080f6 aeb0081d 250039e3 6363b0a0 380fc096 6d18653e da7c1612>;
"p_event" = <acf2f48d 3d5ef365 6e6153a2 268ab4d2 9c4776ed 6165781e f86c0bbc 5b8bfe90>;
"p_type" = <36aaae5d db755d03 9a66e7b0 703ca8bf 5de4210a c6c9e8e3 ea77b8f4 6fd8f8fb>;
penalty = <a8ff8a90 08434fec 24caa525 b16972eb f9a35891 54945888 e68d6faf 7d7aea9f>;
"penalty_event" = <09ef67b3 238a32e0 1a2526d6 82374563 c7275b43 a11d26df fa8447b4 ac7f1175>;
"penalty_type" = <3cdcaf67 0748f85e 0b300ba0 4119f7c2 04cf6a39 1b836ec8 5850f3e6 3662e8ff>;
player = <9d572c6d 15c11f5f 5d4aa3d0 10b75ea3 fa3dd352 1f89a53f f3a3f02e b3d1a4c1>;
position = <89407c79 8f0655a6 550666a3 9e87738d fb985882 5ae70c3a 9ca51fd7 50b24a94>;
roster = <34471eca 339a9ab4 ed86afc9 727c17c3 6117156b e726de09 97c979f2 d4272814>;
rules = <0f7d4bc6 5b82e1ee 6b3e9c3d 2c73ea62 78c6bbbb bb02b6c0 0bdc8a5e 2bc1d22d>;
statistic = <b92a539d 6329e839 d24a80ef e4006a28 3ee3cf68 5cbe1342 5a79f9c7 760f3ffe>;
"statistic_event" = <2d6d03bf 53f05b88 ddc692bc ab805dea 210dc3cb 93ea04e9 c2005fe1 d9f817d3>;
"statistic_type" = <84c5603e 008cdbc3 411c883d a0ac485b 160c35c8 f5ce7394 0fc06d2d c72ece9d>;
team = <97de1350 f685c550 8de940e6 e0c6d8fc f2cd1b80 94725d1b 535f0ff3 13474223>;
"weather_conditions" = <23bce103 1dbe85b6 c7b92d66 69c2d334 34baf747 8ae60dcc dee2b5e0 b739bf31>;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = Binary;
NSStoreUUID = "829124BC-14FB-43C5-A845-A630BB9603E9";
"_NSAutoVacuumLevel" = 2;
}, reason=Can't find model for source store}, {
URL = "file:///Users/pubnubcvconover/Library/Developer/CoreSimulator/Devices/91D7C4F6-34CA-4761-913F-C0B50E753469/data/Containers/Data/Application/ED789ADC-FB9C-43E2-8FDE-E02D80DD43E6/Documents/Stats_Pad.bin";
metadata = {
NSPersistenceFrameworkVersion = 641;
NSStoreModelVersionHashes = {
"field_conditions" = <1a8f23c4 a8f9f08a 7504bd89 b6c608df 89106202 f9c81f02 2441924c 12245334>;
"field_layout" = <da72d767 8f4c3614 fe56ab18 37905a4e b7890395 03515759 46c20c7b 78cbb6cb>;
game = <8f8c1e3b 595416df 4164209d 35268bfd e4f41bf7 aed776a9 3bcfe86a dea6fe6a>;
gender = <bcdc57c3 7ad84924 40c67207 735167f4 e773c4b8 6fc53316 b9fe0220 4e53fad8>;
levels = <7aa35176 e55edff3 7ac01812 5cc17a05 60013487 92196c1d 366a437b a108a9ef>;
p = <593e105a 8ce080f6 aeb0081d 250039e3 6363b0a0 380fc096 6d18653e da7c1612>;
"p_event" = <acf2f48d 3d5ef365 6e6153a2 268ab4d2 9c4776ed 6165781e f86c0bbc 5b8bfe90>;
"p_type" = <36aaae5d db755d03 9a66e7b0 703ca8bf 5de4210a c6c9e8e3 ea77b8f4 6fd8f8fb>;
penalty = <a8ff8a90 08434fec 24caa525 b16972eb f9a35891 54945888 e68d6faf 7d7aea9f>;
"penalty_event" = <09ef67b3 238a32e0 1a2526d6 82374563 c7275b43 a11d26df fa8447b4 ac7f1175>;
"penalty_type" = <3cdcaf67 0748f85e 0b300ba0 4119f7c2 04cf6a39 1b836ec8 5850f3e6 3662e8ff>;
player = <9d572c6d 15c11f5f 5d4aa3d0 10b75ea3 fa3dd352 1f89a53f f3a3f02e b3d1a4c1>;
position = <89407c79 8f0655a6 550666a3 9e87738d fb985882 5ae70c3a 9ca51fd7 50b24a94>;
roster = <34471eca 339a9ab4 ed86afc9 727c17c3 6117156b e726de09 97c979f2 d4272814>;
rules = <0f7d4bc6 5b82e1ee 6b3e9c3d 2c73ea62 78c6bbbb bb02b6c0 0bdc8a5e 2bc1d22d>;
statistic = <b92a539d 6329e839 d24a80ef e4006a28 3ee3cf68 5cbe1342 5a79f9c7 760f3ffe>;
"statistic_event" = <2d6d03bf 53f05b88 ddc692bc ab805dea 210dc3cb 93ea04e9 c2005fe1 d9f817d3>;
"statistic_type" = <84c5603e 008cdbc3 411c883d a0ac485b 160c35c8 f5ce7394 0fc06d2d c72ece9d>;
team = <97de1350 f685c550 8de940e6 e0c6d8fc f2cd1b80 94725d1b 535f0ff3 13474223>;
"weather_conditions" = <23bce103 1dbe85b6 c7b92d66 69c2d334 34baf747 8ae60dcc dee2b5e0 b739bf31>;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = Binary;
NSStoreUUID = "829124BC-14FB-43C5-A845-A630BB9603E9";
"_NSAutoVacuumLevel" = 2;
};
reason = "Can't find model for source store";
}
2016-02-28 16:59:44.228 Lacrosse-Stats[4205:95840] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'team''
*** First throw call stack:
(
0 CoreFoundation 0x03ae1a14 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x035a2e02 objc_exception_throw + 50
2 CoreData 0x0321c859 +[NSEntityDescription entityForName:inManagedObjectContext:] + 281
3 Lacrosse-Stats 0x001c3619 -[SPTeamsController setTeams] + 217
4 Lacrosse-Stats 0x001c4b55 -[SPTeamsController viewDidLoad] + 741
5 UIKit 0x01e8b2ae -[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 44
6 UIKit 0x01e8fdce -[UIViewController loadViewIfRequired] + 1384
7 UIKit 0x01edb9f9 -[UINavigationController _layoutViewController:] + 52
8 UIKit 0x01edc2b1 -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 421
9 UIKit 0x01edc458 -[UINavigationController _startTransition:fromViewController:toViewController:] + 145
10 UIKit 0x01edd854 -[UINavigationController _startDeferredTransitionIfNeeded:] + 1038
11 UIKit 0x01edeada -[UINavigationController __viewWillLayoutSubviews] + 68
12 UIKit 0x020bac4a -[UILayoutContainerView layoutSubviews] + 252
13 UIKit 0x01d90008 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 810
14 libobjc.A.dylib 0x035b7059 -[NSObject performSelector:withObject:] + 70
15 QuartzCore 0x0111480a -[CALayer layoutSublayers] + 144
16 QuartzCore 0x011084ee _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 388
17 QuartzCore 0x01108352 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
18 QuartzCore 0x010fae8b _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 317
19 QuartzCore 0x0112ee03 _ZN2CA11Transaction6commitEv + 561
20 QuartzCore 0x01130674 _ZN2CA11Transaction17flush_transactionEv + 50
21 UIKit 0x01ce6bf8 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke_2 + 111
22 CoreFoundation 0x039fb6e0 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 16
23 CoreFoundation 0x039f1063 __CFRunLoopDoBlocks + 195
24 CoreFoundation 0x039f0798 __CFRunLoopRun + 1016
25 CoreFoundation 0x039f00e6 CFRunLoopRunSpecific + 470
26 CoreFoundation 0x039efefb CFRunLoopRunInMode + 123
27 GraphicsServices 0x044b1664 GSEventRunModal + 192
28 GraphicsServices 0x044b14a1 GSEventRun + 104
29 UIKit 0x01cc3bfa UIApplicationMain + 160
30 Lacrosse-Stats 0x000ecab9 main + 121
31 libdyld.dylib 0x03f54a21 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Perhaps some architecture build setting I need to adjust? Been out of the iOS dev world for a couple years so not aware of all the details of all the changes - more just high level awareness of such things.
I searched on the first error it prints (Error creating LLDB target) and found this: Xcode - Error creating LLDB target
I asked an iOS Engineer that I work with and he nailed it in 5 seconds.
Menu Option for Simulator
Simulator > Reset Content and Setttings...
And thanks to those that provided input.

aabb frustum culling using NEON

i'm trying to optimize aabb box in frustum using NEON (ios, >arm7) and i'm just confused of benchmark results.
NEON version (GLKVector4DotProduct using NEON):
FORCE_INLINE bool box_in_view1(const GLKVector4& min, const GLKVector4& max)
{
#define test_plane(i) { \
const GLKVector4& fp = frustum_plane[i]; \
if (GLKVector4DotProduct(fp, GLKVector4Make(min.x, min.y, min.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(max.x, min.y, min.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(min.x, max.y, min.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(max.x, max.y, min.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(min.x, min.y, max.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(max.x, min.y, max.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(min.x, max.y, max.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(max.x, max.y, max.z, 1.0f)) <= 0.0f) { \
return false; \
} \
}
test_plane(0);
test_plane(1);
test_plane(2);
test_plane(3);
test_plane(4);
test_plane(5);
return true;
}
and without NEON:
FORCE_INLINE bool box_in_view2(const GLKVector4& min, const GLKVector4& max)
{
#define test_plane(i) { \
const GLKVector4& fp = frustum_plane[i]; \
float negw = -fp.w; \
if (fp.x * min.x + fp.y * min.y + fp.z * min.z <= negw && \
fp.x * max.x + fp.y * min.y + fp.z * min.z <= negw && \
fp.x * min.x + fp.y * max.y + fp.z * min.z <= negw && \
fp.x * max.x + fp.y * max.y + fp.z * min.z <= negw && \
fp.x * min.x + fp.y * min.y + fp.z * max.z <= negw && \
fp.x * max.x + fp.y * min.y + fp.z * max.z <= negw && \
fp.x * min.x + fp.y * max.y + fp.z * max.z <= negw && \
fp.x * max.x + fp.y * max.y + fp.z * max.z <= negw) { \
return false; \
} \
}
test_plane(0);
test_plane(1);
test_plane(2);
test_plane(3);
test_plane(4);
test_plane(5);
return true;
}
in simple benchmark timings are:
box_in_view1: 1.9704s
box_in_view2: 0.0013s
it's 10 000 000 tests with static aabb box and static frustum (cube is inside so all tests returns true).
Tested on ipad3, ios7, compiler opt flags: -Ofast -ffast-math
I'm sure that GLKVector4DotProduct() really using NEON instrics in ARM_NEON path. Any explanation why is NEON results so much slower and why?
Below is the FULLY OPTIMIZED version that must be much faster than your current one :
/*
fanicBoxInView
Copyright (C) 2014 Jake Lee
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// int fanicBoxInView(void *pMin, void *pMax, void *pFp, unsigned int count);
// assert : count >= 4
.text
.arm
.global fanicBoxInView
pMin .req r0
pMax .req r1
pFp .req r2
count .req r3
.align 5
.func
fanicBoxInView:
vld1.32 {q12}, [pMin]
vld1.32 {q13}, [pMax]
subs count, count, #4
vmov.i32 q14, #0
vmov.i32 q15, #0
bxmi lr
vpush {q6-q7}
vzip.32 q12, q13
1:
vld1.32 {q0,q1}, [pFp]!
vld1.32 {q2,q3}, [pFp]!
pld [pFp, #64*3]
subs count, count, #4
vdup.32 d20, d1[1]
vdup.32 d21, d3[1]
vdup.32 d22, d5[1]
vdup.32 d23, d7[1]
vmul.f32 d12, d25, d0[1]
vmul.f32 d13, d25, d2[1]
vmul.f32 d14, d25, d4[1]
vmul.f32 d15, d25, d6[1]
vneg.f32 q10, q10
vneg.f32 q11, q11
vmul.f32 d16, d26, d1[0]
vmul.f32 d17, d26, d3[0]
vmul.f32 d18, d26, d5[0]
vmul.f32 d19, d26, d7[0]
vmls.f32 d20, d24, d0[0]
vmls.f32 d21, d24, d2[0]
vmls.f32 d22, d24, d4[0]
vmls.f32 d23, d24, d6[0]
vrev64.32 q0, q6
vrev64.32 q1, q7
vadd.f32 q6, q6, q8
vadd.f32 q7, q7, q9
vadd.f32 q8, q8, q0
vadd.f32 q9, q9, q1
vrev64.32 q0, q6
vrev64.32 q1, q7
vrev64.32 q2, q8
vrev64.32 q3, q9
vcgt.f32 q6, q6, q10
vcgt.f32 q7, q7, q11
vcgt.f32 q8, q8, q10
vcgt.f32 q9, q9, q11
vcgt.f32 q0, q0, q10
vcgt.f32 q1, q1, q11
vcgt.f32 q2, q2, q10
vcgt.f32 q3, q3, q11
vorr q6, q7, q6
vorr q8, q9, q8
vorr q0, q1, q0
vorr q2, q3, q2
vorr q14, q6, q14
vorr q15, q8, q15
vorr q14, q14, q0
vorr q15, q15, q2
bpl 1b
cmp count, #-4
add pFp, pFp, count, lsl #2
bgt 1b
vorr q14, q15, q14
vpop {q6-q7}
vmov r0, r1, d28
vmov r2, r3, d29
orr r0, r1, r0
orr r2, r3, r2
orr r0, r2, r0
bx lr
.endfunc
.end
The syntax above is for Linaro GCC. You'll have to do some changes for XCode:
How do I use the ARM assembler in XCode?
Note that you have to assert (count >= 4);
Also note that the code runs most efficiently when (count % 4 == 0);
Have fun.
PS : I'm a professional optimizer with "optimization on demand" practices, and my clients weren't very pleased with my recent activities providing fully optimized codes here for free. Therefore, I was forced to make it GPL.

I have inserted an image into pdf digital signature layer n2 using mupdf, but it not showed up

I am using mupdf(git clone at commit 2014/3/5 4:05) to sign a pdf.
And I've already succeeded to sign a digital signature in pdf with function 'pdf_sign_signature'.
Now I'm trying to insert an image into layer n2 of that signature when I'm signing it.
There's a function called 'pdf_set_signature_appearance' in '/source/pdf/pdf-appearance.c'.
I try to add codes below to insert the image:
image_doc = (image_document *)fz_open_document(ctx, jpgFilePathAndName);
fz_fill_image(dev, image_doc->image, page_ctm, 1.0f);
these codes are inserted between:
rect = annot->rect;
rect.x0 = (rect.x0 + rect.x1)/2.0f;
text = fit_text(ctx, &font_rec, (char *)bufstr, &rect);
fz_fill_text(dev, text, page_ctm, cs, font_rec.da_rec.col, 1.0f);
and
rect = annot->rect;
fz_transform_rect(&rect, page_ctm);
pdf_set_annot_appearance(doc, annot, &rect, dlist);
After executing, I got a pdf file like this:
%PDF-1.4
%μῦ
1 0 obj
<<
/Type /Font
/BaseFont /Helvetica
/Subtype /Type1
/Encoding /WinAnsiEncoding
>>
endobj
2 0 obj
<<
/Length 63
>>
stream
q
BT
36 806 Td
0 -18 Td
/F1 12 Tf
(Hello World!)Tj
0 0 Td
ET
Q
endstream
endobj
3 0 obj
<<
/Count 1
/Type /Pages
/ITXT (5.3.0)
/Kids [ 4 0 R ]
>>
endobj
4 0 obj
<<
/Annots 10 0 R
/Contents 2 0 R
/MediaBox [ 0 0 595 842 ]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 1 0 R
>>
/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>>
/Type /Page
>>
endobj
5 0 obj
<<
/AcroForm 8 0 R
/Metadata 9 0 R
/Pages 3 0 R
/Type /Catalog
>>
endobj
6 0 obj
<<
/CreationDate (D:20120620091727+02'00')
/ModDate (D:20120804153425+02'00')
/Producer (iText\256 5.3.0 \2512000-2012 1T3XT BVBA)
>>
endobj
7 0 obj
<<
/AP <<
/N 17 0 R
>>
/DA (/Helv 0 Tf 0 g)
/F 4
/FT /Sig
/MK <<
>>
/P 4 0 R
/Rect [ 41.3670998 713.710022 237.352997 781.257996 ]
/Subtype /Widget
/T (Signature1)
/Type /Annot
/V 15 0 R
>>
endobj
8 0 obj
<<
/DA (/Helv 0 Tf 0 g )
/DR <<
/Encoding <<
/PDFDocEncoding 14 0 R
>>
/Font <<
/Helv 12 0 R
/ZaDb 13 0 R
>>
/XObject <<
/DSz 11 0 R
>>
>>
/Fields [ 7 0 R ]
/SigFlags 1
>>
endobj
9 0 obj
<<
/Length 3304
/Subtype /XML
/Type /Metadata
>>
stream
<?xpacket begin="Ôªø" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:08:04 ">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:xmp="http://ns.adobe.com/xap/1.0/">
<xmp:CreateDate>2012-06-20T09:17:27+02:00</xmp:CreateDate>
<xmp:ModifyDate>2012-08-04T15:34:25+02:00</xmp:ModifyDate>
<xmp:MetadataDate>2012-08-04T15:34:25+02:00</xmp:MetadataDate>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
<pdf:Producer>iText® 5.3.0 ©2000-2012 1T3XT BVBA</pdf:Producer>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:format>application/pdf</dc:format>
</rdf:Description>
<rdf:Description rdf:about=""
xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">
<xmpMM:DocumentID>uuid:547fb234-f327-4f3d-8dd1-7b7ea87df336</xmpMM:DocumentID>
<xmpMM:InstanceID>uuid:72437fbf-7b45-4062-98f1-2b53d3ad86d0</xmpMM:InstanceID>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>endstream
endobj
10 0 obj
[ 7 0 R ]
endobj
11 0 obj
<<
/BBox [ 41.3670998 713.710022 237.352997 781.257996 ]
/Length 67
/Resources <<
/XObject <<
/Img0 16 0 R
>>
>>
/Subtype /Form
/Type /XObject
/Matrix [ 1 0 0 1 0 0 ]
>>
stream
1.000000 0.000000 0.000000 -1.000000 0.000000 1.000000 cm
/Img0 Do
endstream
endobj
12 0 obj
<<
/BaseFont /Helvetica
/Encoding 14 0 R
/Name /Helv
/Subtype /Type1
/Type /Font
>>
endobj
13 0 obj
<<
/BaseFont /ZapfDingbats
/Name /ZaDb
/Subtype /Type1
/Type /Font
>>
endobj
14 0 obj
<<
/Differences [ 24 /breve /caron /circumflex /dotaccent /hungarumlaut
/ogonek /ring /tilde 39 /quotesingle 96 /grave 128 /bullet
/dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction
/guilsinglleft /guilsinglright /minus /perthousand /quotedblbase
/quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase
/trademark /fi /fl /Lslash /OE /Scaron /Ydieresis /Zcaron
/dotlessi /lslash /oe /scaron /zcaron 160 /Euro 164 /currency
166 /brokenbar 168 /dieresis /copyright /ordfeminine 172
/logicalnot /.notdef /registered /macron /degree /plusminus
/twosuperior /threesuperior /acute /mu 183 /periodcentered
/cedilla /onesuperior /ordmasculine 188 /onequarter /onehalf
/threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis
/Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis
/Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve
/Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash
/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls
/agrave /aacute /acircumflex /atilde /adieresis /aring /ae
/ccedilla /egrave /eacute /ecircumflex /edieresis /igrave
/iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute
/ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute
/ucircumflex /udieresis /yacute /thorn /ydieresis ]
/Type /Encoding
>>
endobj
15 0 obj
<<
/ByteRange[0 6712 10814 12756] /Contents
...
/Filter /Adobe.PPKLite
/SubFilter /adbe.pkcs7.detached
>>
endobj
16 0 obj
<<
/Type /XObject
/Subtype /Image
/Width 400
/Height 332
/ColorSpace /DeviceRGB
/BitsPerComponent 8
/Length 11097
>>
stream
...
endstream
endobj
17 0 obj
<<
/BBox [ 41.3670998 713.710022 237.352997 781.257996 ]
/FormType 1
/Length 7
/Matrix [ 1 0 0 1 0 0 ]
/Resources <<
/ProcSet [ /PDF /Text ]
/XObject <<
/FRM 18 0 R
>>
>>
/Subtype /Form
/Type /XObject
>>
stream
/FRM Doendstream
endobj
18 0 obj
<<
/BBox [ 41.3670998 713.710022 237.352997 781.257996 ]
/FormType 1
/Length 51
/Matrix [ 1 0 0 1 0 0 ]
/Resources <<
/ProcSet [ /PDF /Text ]
/XObject <<
/n0 19 0 R
/n2 11 0 R
>>
>>
/Subtype /Form
/Type /XObject
>>
stream
q 1 0 0 1 0 0 cm /n0 Do Q q 1 0 0 1 0 0 cm /n2 Do Qendstream
endobj
19 0 obj
<<
/BBox [ 41.3670998 713.710022 237.352997 781.257996 ]
/FormType 1
/Length 9
/Matrix [ 1 0 0 1 0 0 ]
/Resources <<
/ProcSet [ /PDF /Text ]
>>
/Subtype /Form
/Type /XObject
>>
stream
% DSBlankendstream
endobj
xref
0 20
0000000000 65536 f
0000000017 00000 n
0000000123 00000 n
0000000238 00000 n
0000000320 00000 n
0000000544 00000 n
0000000634 00000 n
0000000790 00000 n
0000001026 00000 n
0000001272 00000 n
0000004664 00000 n
0000004691 00000 n
0000004990 00000 n
0000005101 00000 n
0000005196 00000 n
0000006628 00000 n
0000010882 00000 n
0000022144 00000 n
0000022423 00000 n
0000022763 00000 n
trailer
<<
/Size 20
/Info 6 0 R
/Root 5 0 R
/ID [ <D0151A7ADF2410CF3E72A04B9CB83452> <FA2030FCC5A66742887F23E51DEC5875> ]
>>
startxref
23003
%%EOF
It seems to be correct, since there's /n2 11 0 R in 18 0 obj and /Img0 16 0 R in 11 0 obj and 16 0 obj looks like a well-formed Image XObject.
But the image doesn't show up when I using pdf reader to open this pdf.
Could someone please give me a clue about what's wrong with this pdf file, and how to insert the image correctly.
Thanks a lot.
ps.
signed_with_image_only.pdf
signed_with_text_and_image.pdf
signed_with_image_only.pdf is the pdf I've added '\n' before 'endstream'. You can see image doesn't show up in the form which is below 'Hello World!'.
signed_with_text_and_image.pdf is pretty much the same as signed_with_image_only.pdf, but I put some text in layer n2 to show you text insertion is ok. The same image is also inserted, and it also not showed up.
The transformation matrix is not right.
You can use other PDF utility, like PDFBox, to add an image into digital signature appearance, then analyze the transformation matrix on image painting, also pay attention on its BBOx.
I don't know if it's the text formatting but you have a number of streams (objects 17, 18 and 19) where the "endstream" that denotes the end of the stream data is not being written correctly. The "endstream" should be on a line of its own, and a PDF file requires whitespace between tokens and operators. Therefore, things like
/FRM Doendstream
are invalid syntax, they should be written like
/FRM Do
endstream
For images, the current transform matrix must transform from the 1 unit square that images are specified in, to the desired size in PDF units. You're using a transformation matrix of [1 0 0 -1 0 1] to position and scale the image XObject, which will not give your desired result. Typically, for an unrotated image you'll want to use something like [width 0 0 height Xpos Ypos]. Also, I always recommend enclosing image XObject invocation in a graphic state save/restore so that the CTM required can be popped off the graphic state stack.
Finally, looking at the file in Dropbox your image is damaged. It specifies a width of 400 rasters and a height of 332 rasters - in RGB format, the image should have a length of 398,400 but only has a length of 11097. This is way too short for this image data stream. It looks like this is compressed data, in DCT compressed format. For this to render properly you need to specify that it is compressed and in the format, e.g. add
/Filter /DCTDecode
to the image dictionary.

Resources