############################################################################ # # File: puzz.icn # # Subject: Program to create word search puzzle # # Author: Chris Tenaglia # # Date: February 18, 1996 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program creates word search puzzles. # ############################################################################ global matrix, # the actual puzzle board width, # width of the puzzle height, # height of the puzzle completed # number of completed word placements procedure main(param) local i, j, line, pass, tokens, word, words # # initial set up : x=20, y=20 by default # width := param[1] | 20 height := param[2] | 20 words := [] # # load words to place in a space delimited # file. more than one word per line is ok. # while line := map(read()) do { tokens := parse(line,' \t') while put(words,pop(tokens)) } # # get ready for main processing # matrix := table(" ") pass := 0 completed := 0 &random:= map(&clock,":","0") # # here's the actual word placement rouinte # every word := !words do place(word) # # fill in the unchosen areas with random alphas # every i := 1 to height do every j := 1 to width do if matrix[i||","||j] == " " then matrix[i||","||j] := ?(&ucase) # # output results (for the test giver, words are lcase, noise is ucase) # write(completed," words inserted out of ",*words," words.\n") write("\nNow for the puzzle you've been waiting for! (ANSWER)\n") every i := 1 to height do { every j := 1 to width do writes(matrix[i||","||j]," ") write() } # # output results (for the test taker, everything is upper case # write("\fNow for the puzzle you've been waiting for! (PUZZLE)\n") every i := 1 to height do { every j := 1 to width do writes(map(matrix[i||","||j],&lcase,&ucase)," ") write() } end # # this procedure tries to place the word in a copy of the matrix # if successful the updated copy is moved into the original # if not, the problem word is skipped after 20 tries # procedure place(str) local byte, construct, direction, item, pass, x, xinc, y, yinc static xstep,ystep initial { xstep := [0,1,1,1,0,-1,-1,-1] ystep := [-1,-1,0,1,1,1,0,-1] } pass := 0 repeat { if (pass +:= 1) > 20 then { write("skipping ",str) fail } direction := ?8 xinc := integer(xstep[direction]) yinc := integer(ystep[direction]) if xinc < 0 then x := *str + ?(width - *str) if xinc = 0 then x := ?height if xinc > 0 then x := ?(width - *str) if yinc < 0 then y := *str + ?(height - *str) if yinc = 0 then y := ?width if yinc > 0 then y := ?(height - *str) if (x < 1) | (y < 1) then stop(str," too long.") construct := copy(matrix) item := str write("placing ",item) every byte := !item do { if (construct[x||","||y] ~== " ") & (construct[x||","||y] ~== byte) then break next construct[x||","||y] := byte x +:= xinc y +:= yinc } matrix := copy(construct) completed +:= 1 return "ok" } # end repeat return "ok" end # # parse a string into a list with respect to a delimiter (cset) # procedure parse(line,delims) local tokens static chars chars := &cset -- delims tokens := [] line ? while tab(upto(chars)) do put(tokens,tab(many(chars))) return tokens end