|
|
1.1 root 1: lifedemo = proc ()
2: qi = sequence[int]
3: ai = array[int]
4: ab = array[bool]
5: pwidth = 8
6: bwidth: int := int$parse(xdemo_default("life", "BorderWidth"))
7: except when not_found, overflow, bad_format: bwidth := 2 end
8: back: x_pixmap := x_display$white()
9: bdr: x_pixmap := x_display$black()
10: backpix: int := WhitePixel
11: forepix: int := BlackPixel
12: mousepix: int := BlackPixel
13: if x_display$cells() > 2
14: then begin
15: r, g, b: int := x_parse_color(xdemo_default("life", "Border"))
16: bdr := x_pixmap$tile(x_display$alloc_color(r, g, b))
17: end except when not_found: end
18: begin
19: r, g, b: int := x_parse_color(xdemo_default("life", "Background"))
20: backpix := x_display$alloc_color(r, g, b)
21: back := x_pixmap$tile(backpix)
22: end except when not_found: end
23: begin
24: r, g, b: int := x_parse_color(xdemo_default("life", "Foreground"))
25: forepix := x_display$alloc_color(r, g, b)
26: mousepix := forepix
27: end except when not_found: end
28: begin
29: r, g, b: int := x_parse_color(xdemo_default("life", "Mouse"))
30: mousepix := x_display$alloc_color(r, g, b)
31: end except when not_found: end
32: end
33: f: x_font := x_font$create("8x13")
34: w: x_window, cwidth, cheight: int := x_tcons("life", back, bdr,
35: xdemo_geometry(), "=40x40+1+1",
36: f, 8, 8, 1, 3, 3, bwidth)
37: x_font$destroy(f)
38: x_window$set_resize(w, 1, 8, 1, 8)
39: w.name := "life"
40: w.input := ButtonPressed + UnmapWindow
41: x_window$map(w)
42: w.input := ButtonPressed + ExposeRegion + UnmapWindow
43: cr: x_cursor := x_cursor$scons(arrow_width, arrow_height,
44: arrow, arrow_mask,
45: backpix, mousepix,
46: arrow_x, arrow_y, GXcopy)
47: w.cursor := cr
48: stopped: bool := false
49: ev: event := x_input$empty_event()
50: while true do
51: sx, sy, width, height, bw, ms, wk: int, iw: x_window := x_window$query(w)
52: if height <= 30 cor width <= 30
53: then x_window$destroy(w)
54: return
55: end
56: x_window$clear(w)
57: width := (width - 1) / pwidth
58: prob: int := int$min(10, width / 2)
59: height := (height - 1) / pwidth + 2
60: span: int := width * height
61: arena: ab := ab$fill(0, span, false)
62: xcoords: ai := ai$fill(0, span, 0)
63: ycoords: ai := ai$fill(0, span, 0)
64: for point: int in int$from_to(0, span - 1) do
65: xcoords[point] := (point // width) * pwidth + 1
66: ycoords[point] := (point / width - 1) * pwidth + 1
67: end
68: neighbor_list: ai := ai$predict(1, span / 4)
69: neighbors: ai := ai$fill(0, span, 0)
70: neighbor_map: ai := ai$fill(0, span, 0)
71: generation: int := 1
72: offset: qi := qi$[-(width + 1), -width, -(width - 1), -1,
73: 1, width - 1, width, width + 1]
74: change_sets: ai := ai$predict(1, span)
75: change_clears: ai := ai$predict(1, span)
76: span := span - width
77: while true do
78: while stopped cor
79: (ai$empty(change_sets) cand ai$empty(change_clears)) cor
80: x_input$pending() do
81: x_input$deq(ev)
82: if ev.kind = UnmapWindow
83: then x_input$deq(ev) end
84: if ev.kind = ButtonPressed cand ev.value = LeftButton
85: then for point: int in int$from_to(width, span - 1) do
86: if random$next(prob) ~= 0
87: then continue end
88: if neighbor_map[point] ~= generation
89: then neighbor_map[point] := generation
90: ai$addh(neighbor_list, point)
91: end
92: if arena[point]
93: then ai$addh(change_clears, point)
94: else ai$addh(change_sets, point)
95: end
96: end
97: break
98: elseif ev.kind = ButtonPressed cand ev.value = MiddleButton
99: then stopped := ~stopped
100: elseif ev.kind = ButtonPressed cand ev.value = RightButton
101: then for i: int in int$from_to(0, span - 1) do
102: arena[i] := false
103: neighbors[i] := 0
104: neighbor_map[i] := 0
105: end
106: generation := 1
107: x_window$clear(w)
108: ai$trim(change_sets, 1, 0)
109: ai$trim(change_clears, 1, 0)
110: elseif ev.kind = ExposeWindow cand
111: (width ~= (ev.x - 1) / pwidth cor
112: height ~= (ev.y - 1) / pwidth + 2)
113: then exit changed
114: else x1: int := ev.x
115: y1: int := ev.y
116: x: int := (x1 + ev.x0 - 1) / pwidth
117: y: int := (y1 + ev.y0 - 1) / pwidth
118: x1 := x1 / pwidth
119: y1 := y1 / pwidth
120: for i: int in int$from_to(x1, x) do
121: for j: int in int$from_to(y1, y) do
122: point: int := j * width + i
123: if arena[point]
124: then x_window$pix_set(w, forepix,
125: xcoords[point],
126: ycoords[point],
127: pwidth - 1, pwidth - 1)
128: end except when bounds: end
129: end
130: end
131: end
132: end
133: for point: int in ai$elements(change_clears) do
134: x_window$pix_set(w, backpix,
135: xcoords[point], ycoords[point],
136: pwidth - 1, pwidth - 1)
137: arena[point] := false
138: for i: int in qi$elements(offset) do
139: begin
140: index: int := point + i
141: neighbors[index] := neighbors[index] - 1
142: if neighbor_map[index] ~= generation
143: then neighbor_map[index] := generation
144: ai$addh(neighbor_list, index)
145: end
146: end except when bounds: end
147: end
148: end
149: ai$trim(change_clears, 1, 0)
150: for point: int in ai$elements(change_sets) do
151: x_window$pix_set(w, forepix,
152: xcoords[point], ycoords[point],
153: pwidth - 1, pwidth - 1)
154: arena[point] := true
155: for i:int in qi$elements(offset) do
156: begin
157: index: int := point + i
158: neighbors[index] := neighbors[index] + 1
159: if neighbor_map[index] ~= generation
160: then neighbor_map[index] := generation
161: ai$addh(neighbor_list, index)
162: end
163: end except when bounds: continue end
164: end
165: end
166: ai$trim(change_sets, 1, 0)
167: generation := generation + 1
168: for point: int in ai$elements(neighbor_list) do
169: n: int := neighbors[point]
170: if n = 3
171: then if ~arena[point] cand
172: point >= width cand point < span
173: then ai$addh(change_sets, point) end
174: elseif n ~= 2
175: then if arena[point]
176: then ai$addh(change_clears, point) end
177: end
178: end
179: ai$trim(neighbor_list, 1, 0)
180: end except when changed: end
181: end
182: end lifedemo
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.