import from Internet Archive
[vncperl.git] / life.pl
1 use strict;\r
2 use warnings;\r
3 use VNC::Server;\r
4 \r
5 \r
6 my $life_cell_pixel_size = 5 ;\r
7 my $life_cells_per_col   = 20 ;\r
8 my $life_cells_per_row   = 20;\r
9 \r
10 my $running = 0;\r
11 \r
12 #\r
13 # Init the life data\r
14 #\r
15 my @life_data;\r
16 \r
17 foreach my $i (0..$life_cells_per_row-1) {\r
18         foreach my $j (0..$life_cells_per_col-1) {\r
19                 $life_data[$i][$j] = int(rand(2));\r
20         }\r
21 }\r
22 \r
23 sub count_neighbors {\r
24         my ($i,$j) = @_ ;\r
25 \r
26         my $count =0 ;\r
27         \r
28         foreach my $q ( ($i-1)..($i+1)) {\r
29                 foreach my $w ( ($j-1)..($j+1)) {\r
30                         if ( ($q>=0) && ($q<$life_cells_per_row) && \r
31                                  ($w>=0) && ($w<$life_cells_per_col) &&\r
32                                  (($q!=$i) || ($w!=$j))\r
33                                  ) {\r
34                                 if ($life_data[$q][$w]==1) {\r
35                                         $count++ ;\r
36                                 }\r
37                         }\r
38                 }\r
39         }\r
40         return $count;\r
41 }\r
42 \r
43 \r
44 my $s = new VNC::Server( Port=>2, \r
45                                                  Idle=>1, \r
46                                                  Caption=>'Game of VNCLife',\r
47                                                  Width => $life_cell_pixel_size * $life_cells_per_row, \r
48                                                  Height => $life_cell_pixel_size * $life_cells_per_col,\r
49                                                  IdleHandler => \&next_turn,\r
50                                                  KeyEventHandler => \&keyboard, \r
51                                                  PointerEventHandler => \&pointer,\r
52                                                  UpdateDisplayHandler => \&updater\r
53                                                 );\r
54 \r
55 $s->vnc_server_loop;\r
56 \r
57 sub keyboard {\r
58         my ($vnc, $down, $key) = @_ ;\r
59 \r
60         #act only on key released\r
61         if ($down==0) {\r
62 \r
63                 # R = randomize\r
64                 if ($key==ord('R') || $key==ord('r')) {\r
65                         foreach my $i (0..$life_cells_per_row-1) {\r
66                                 foreach my $j (0..$life_cells_per_col-1) {\r
67                                         $life_data[$i][$j] = int(rand(2));\r
68                                 }\r
69                         }\r
70                         $s->update_all_displays;\r
71                 }\r
72 \r
73                 # C = clear\r
74                 if ($key==ord('C') || $key==ord('c')) {\r
75                         foreach my $i (0..$life_cells_per_row-1) {\r
76                                 foreach my $j (0..$life_cells_per_col-1) {\r
77                                         $life_data[$i][$j] = 0;\r
78                                 }\r
79                         }\r
80                         $s->update_all_displays;\r
81                 }\r
82 \r
83                 # Q = Quit\r
84                 if ($key==ord('Q') || $key==ord('q')) {\r
85                         $vnc->disconnect();\r
86                 }\r
87 \r
88                 # S = Start/Stop\r
89                 if ($key==ord('S') || $key==ord('s')) {\r
90                         if ($running) {\r
91                                 print "Stoping!\n";\r
92                                 $running = undef ;\r
93                         } else {\r
94                                 print "Starting!\n";\r
95                                 $running = 1;\r
96                         }\r
97                 }\r
98         }\r
99 }\r
100 \r
101 sub pointer {\r
102         my ($vnc,$mask,$x,$y) = @_ ;\r
103 \r
104         if ($mask!=0) {\r
105                 my $i = $x / $life_cell_pixel_size ;\r
106                 my $j = $y / $life_cell_pixel_size ;\r
107 \r
108                 $life_data[$i][$j] = ($mask==1) ? 1 : 0 ;\r
109 \r
110                 $s->update_all_displays;\r
111         }\r
112 }\r
113 \r
114 \r
115 sub updater {\r
116         my ($vnc, $inc, $x,$y,$w,$h) = @_ ;\r
117         my $codec = $vnc->{CODEC};\r
118 \r
119         my @rects ;\r
120         my $red_pixel = $codec->encode_pixel(255,0,0);\r
121         my $white_pixel = $codec->encode_pixel(255,255,255);\r
122 \r
123         foreach my $i (0..$life_cells_per_row-1) {\r
124                 foreach my $j (0..$life_cells_per_col-1) {\r
125                         if ($life_data[$i][$j]==1) {\r
126                                 push @rects, $codec->encode_rre_subrect( $red_pixel ,$i*$life_cell_pixel_size, $j*$life_cell_pixel_size,$life_cell_pixel_size,$life_cell_pixel_size);\r
127                         }\r
128                 }\r
129         }\r
130         my $data = $codec->encode_framebuffer_update( $codec->encode_rre($white_pixel, $x,$y,$w,$h, @rects));\r
131 \r
132         return $data ;\r
133 }\r
134 \r
135 sub next_turn {\r
136         #not running, exit immediately\r
137         return unless ($running);\r
138 \r
139         #calculate the next life phase\r
140         my @new_life_data;\r
141 \r
142         foreach my $i (0..$life_cells_per_row-1) {\r
143                 foreach my $j (0..$life_cells_per_col-1) {\r
144                         $new_life_data[$i][$j] = 0;\r
145                 }\r
146         }\r
147 \r
148         foreach my $i (0..$life_cells_per_row-1) {\r
149                 foreach my $j (0..$life_cells_per_col-1) {\r
150                         my $current = $life_data[$i][$j];\r
151                         my $count = count_neighbors($i,$j);\r
152                         \r
153                         if ($current==1){\r
154                                 if ($count<2 || $count>3) {\r
155                                         $new_life_data[$i][$j] = 0 ;\r
156                                 } else {\r
157                                         $new_life_data[$i][$j] = 1 ;\r
158                                 }\r
159                         }else{\r
160                                 if ($count==3) {\r
161                                         $new_life_data[$i][$j] = 1 ;\r
162                                 } else {\r
163                                         $new_life_data[$i][$j] = 0 ;\r
164                                 }\r
165                         }\r
166                 }\r
167         }\r
168         @life_data = @new_life_data;\r
169         \r
170         $s->update_all_displays;\r
171 }\r