summaryrefslogtreecommitdiff
path: root/ipl/progs/puzz.icn
blob: 363a038e4b15066a234e7283c9de93364e0c8772 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
############################################################################
#
#	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