… | |
… | |
62 | |
62 | |
63 | 1 |
63 | 1 |
64 | } |
64 | } |
65 | |
65 | |
66 | cf::register_attachment minesweeper => |
66 | cf::register_attachment minesweeper => |
67 | on_instantiate => sub { |
67 | on_tick => sub { |
68 | my ($self) = @_; |
68 | my ($self) = @_; |
69 | |
69 | |
70 | my %arg = %{ $self->{options} = delete $self->{minesweeper} }; |
70 | if (my $queue = $self->{queue}) { |
71 | $self->{queue} = []; |
71 | my $count = 4; |
72 | |
72 | |
73 | my $map = $self->{map} = []; |
73 | while (@$queue) { |
|
|
74 | my $i = int rand @$queue; |
|
|
75 | my $ob = splice @$queue, $i, 1, (); |
74 | |
76 | |
75 | for my $x (0 .. $arg{width} - 1) { |
77 | next if $ob->{visible}; |
76 | for my $y (0 .. $arg{height} - 1) { |
|
|
77 | my $ob = $map->[$x][$y] = cf::object::new "minesweeper-unknown"; |
|
|
78 | $ob->set_name ("apply to try your luck or intelligence"); |
|
|
79 | Scalar::Util::weaken ($ob->{meta} = $self); |
|
|
80 | |
78 | |
81 | $ob->attach ("minesweeper_field"); |
79 | apply $ob |
82 | $ob->insert_ob_in_map_at ($self->map, undef, cf::INS_ABOVE_FLOOR_ONLY, |
80 | or next; |
83 | $self->x + $x, $self->y + $y); |
81 | |
|
|
82 | result $self, "success" |
|
|
83 | unless $self->{todo}; |
|
|
84 | |
|
|
85 | $count-- |
|
|
86 | or last; |
84 | } |
87 | } |
85 | } |
88 | } else { |
|
|
89 | my %arg = %{ $self->{options} = delete $self->{minesweeper} }; |
|
|
90 | $self->{queue} = []; |
86 | |
91 | |
87 | # #tiles that need to be uncovered |
92 | my $map = $self->{map} = []; |
88 | $self->{todo} = $arg{width} * $arg{height} - $arg{bombs}; |
|
|
89 | |
93 | |
90 | for (1 .. $arg{bombs}) { |
94 | for my $x (0 .. $arg{width} - 1) { |
91 | my $x = int rand $arg{width}; |
95 | for my $y (0 .. $arg{height} - 1) { |
92 | my $y = int rand $arg{height}; |
96 | my $ob = $map->[$x][$y] = cf::object::new "minesweeper-unknown"; |
|
|
97 | $ob->set_name ("apply to try your luck or intelligence"); |
|
|
98 | Scalar::Util::weaken ($ob->{meta} = $self); |
93 | |
99 | |
94 | redo if $map->[$x][$y]{bomb}; |
100 | $ob->attach ("minesweeper_field"); |
|
|
101 | $ob->insert_ob_in_map_at ($self->map, undef, cf::INS_ABOVE_FLOOR_ONLY, |
|
|
102 | $self->x + $x, $self->y + $y); |
|
|
103 | } |
|
|
104 | } |
95 | |
105 | |
96 | $map->[$x][$y]{bomb} = 1; |
106 | # #tiles that need to be uncovered |
97 | } |
107 | $self->{todo} = $arg{width} * $arg{height} - $arg{bombs}; |
98 | }, |
|
|
99 | on_time => sub { |
|
|
100 | my ($self) = @_; |
|
|
101 | |
108 | |
102 | my $queue = $self->{queue}; |
109 | for (1 .. $arg{bombs}) { |
103 | my $count = 4; |
110 | my $x = int rand $arg{width}; |
|
|
111 | my $y = int rand $arg{height}; |
104 | |
112 | |
105 | while (@$queue) { |
113 | redo if $map->[$x][$y]{bomb}; |
106 | my $i = int rand @$queue; |
|
|
107 | my $ob = splice @$queue, $i, 1, (); |
|
|
108 | |
114 | |
109 | next if $ob->{visible}; |
115 | $map->[$x][$y]{bomb} = 1; |
110 | |
116 | } |
111 | apply $ob |
|
|
112 | or next; |
|
|
113 | |
|
|
114 | result $self, "success" |
|
|
115 | unless $self->{todo}; |
|
|
116 | |
|
|
117 | $count-- |
|
|
118 | or last; |
|
|
119 | } |
117 | } |
120 | |
118 | |
121 | cf::override; |
119 | cf::override; |
122 | }, |
120 | }, |
123 | ; |
121 | ; |