-
Notifications
You must be signed in to change notification settings - Fork 0
/
typing_game.pl
executable file
·173 lines (140 loc) · 4.26 KB
/
typing_game.pl
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/usr/bin/perl
# NOTE: This code is not 100% portable. If you notice that words are not being
# recognized as complete, change this offset variable to equal 1.
my $offset=0;
###############################################################################
# Variable Initializations #
###############################################################################
use strict;
use warnings;
use Time::HiRes qw(usleep gettimeofday);
use Term::ReadKey;
use sigtrap 'handler' => \&end_game, 'INT';
$|=1;
my $DICTIONARY="/usr/games/words.txt";
unless ( -e $DICTIONARY ) {
print "\nERROR: $DICTIONARY does not exist. Get it from github.\n";
exit 1;
}
open (TMP, $DICTIONARY);
my @WORDS = <TMP>;
close (TMP);
my $num_words = @WORDS;
# Game setup
my $increment=10; # How often speed goes up.
my $word_limit=23; # Lose if there are this many words on screen
my @active=();my $word_index=0;
my $alive=1;
my $prev=1;my $curr=1;my $diff=1;
my $input="";
my $x=1;my $y=0; # Determine where cursor is
my $start_time=gettimeofday;
my @template=(3.0, 2.6, 2.4, 2.2, 2.1, 2.0, 1.9, 1.8, 1.7, 1.6, 1.5, 1.4, 1.3, 1.2, 1.1, 1.0);
my @wait=();
my $wait_index=0;
ReadMode 3; # No echo, but you can still send signals.
###############################################################################
# Main functions #
###############################################################################
# Main
sub main {
&setup_wait;
&clear_screen;
&run_game;
&end_game;
}
sub run_game {
while ( $alive ) {
&set_speed;
# Add a word to array of active words.
my $word = &generate_word; chomp $word;
push ( @active, $word );
# Print with new word
&output;
$y++;
# Move cursor to correct position
print "\e[$y;${x}H";
# Make sure game isn't over
if ( scalar(@active) > $word_limit ) {
$alive=0;
next;
}
# Wait for 1-3 seconds before adding next word.
$diff = 0;
$prev = gettimeofday;
while ( $diff < $wait[$wait_index] ) {
# Get non-blocking input
$input = ReadKey(-1);
# Is it the right letter?
if ( defined($input) && defined($active[0]) ) { #prevents error msg
if ( $input eq substr($active[0], $word_index, 1) ) {
$word_index++;
$x++;
print "\e[$y;${x}H";
if ( $word_index >= length($active[0])+$offset ) {
$y--;
$x=1;
$word_index=0;
shift @active;
&output;
print "\e[$y;${x}H";
}
}
}
usleep 100; # So that cpu can do other stuff I guess.
$curr = gettimeofday;
$diff = $curr - $prev;
}
}
}
sub output {
&clear_screen;
print "\e[1;1H";
print join("\n", reverse @active),"\n\n";
my $speed=int($wait_index/$increment);
print "\e[1;72HSpeed: $speed";
}
# One-time sub that takes values from @template and assigns them to @wait.
# This is kind of cryptic, so here goes an explanation:
# 1. The game should get faster every 10 ($increment) seconds.
# 2. @template holds the (decreasing) values that the games uses to know how
# long to wait for in between words.
# 3. This method copies those values to @wait 10 times, so that every second
# that goes by while the game is running correlates to an element of @wait.
# Then, every 10 seconds, the wait will go down.
sub setup_wait {
for my $i (0 .. $#template) {
for my $j ($i*$increment .. $i*$increment+$increment-1) {
@wait[$j]=$template[$i];
}
}
}
# Sets "wait_index" variable which determines how long the program waits before
# adding another word.
sub set_speed {
$curr = gettimeofday;
$wait_index = int($curr - $start_time);
# Don't increment if it's at max speed.
if ( $wait_index >= scalar(@wait) ) {
$wait_index=scalar(@wait)-1;
}
}
sub generate_word {
my $rand = int(rand($num_words));
return "$WORDS[$rand]";
}
sub clear_screen {
print "\e[2J";
}
# Exits and restores sane terminal settings
sub end_game {
$curr = gettimeofday;
my $elapsed = int($curr - $start_time);
print "\e[24;1HYou made it for $elapsed seconds.\n";
system("stty echo");
exit 0;
}
###############################################################################
# Why is this so far down #
###############################################################################
&main