1+ use std:: io:: Write ;
2+ use rand:: Rng ;
3+
4+ /** KINEMA BY RICHARD PAV
5+ * https://github.com/coding-horror/basic-computer-games/blob/main/52_Kinema/kinema.bas
6+ * Direct conversion from BASIC to Rust by Pablo Marques (marquesrs).
7+ * As a faithful translation, many of the code here are done in an unrecommended way by
8+ * today's standards.
9+ *
10+ * ATTENTION: The original code has mathematical imprecision and uses simplifications
11+ * instead of the real formulation, which could lead to incorrect results. I have solved
12+ * this issue, but kept the old lines. To compile the original version, just uncomment the
13+ * code with the OLD label and comment the lines with the NEW label.
14+ * example: gravity is now 9.81 instead of 10
15+ * 17/02/25
16+ */
17+
18+ fn subroutine ( a : f64 , q : & mut i32 ) {
19+ std:: io:: stdout ( ) . flush ( ) . unwrap ( ) ;
20+ //500 INPUT G
21+ let mut input = String :: new ( ) ;
22+ let g;
23+ loop {
24+ std:: io:: stdin ( ) . read_line ( & mut input) . unwrap ( ) ;
25+ match input. trim ( ) . parse :: < f64 > ( ) {
26+ Ok ( e) => { g = e; break ; } ,
27+ Err ( _) => { print ! ( "\n INVALID. TRY AGAIN: " ) ; continue ; } ,
28+ } ;
29+ }
30+ //502 IF ABS((G-A)/A)<.15 THEN 510
31+ if f64:: abs ( ( g-a) /a) < 0.15 {
32+ //510 PRINT "CLOSE ENOUGH."
33+ print ! ( "CLOSE ENOUGH." ) ;
34+ //511 Q=Q+1
35+ * q = * q + 1 ;
36+ }
37+ else {
38+ //504 PRINT "NOT EVEN CLOSE...."
39+ print ! ( "NOT EVEN CLOSE..." ) ;
40+ //506 GOTO 512
41+ }
42+ //512 PRINT "CORRECT ANSWER IS ";A
43+ print ! ( "\n CORRECT ANSWER IS {a:.2}\n " ) ;
44+ //520 PRINT
45+ //530 RETURN
46+ }
47+
48+ fn main ( ) {
49+ let mut rng = rand:: rng ( ) ;
50+
51+ //10 PRINT TAB(33);"KINEMA"
52+ //20 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
53+ //30 PRINT: PRINT: PRINT
54+ //100 PRINT
55+ //105 PRINT
56+ print ! ( "{}KINEMA\n {}CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n \n \n \n " ,
57+ " " . repeat( 33 ) ,
58+ " " . repeat( 15 )
59+ ) ;
60+ loop {
61+ //106 Q=0
62+ let mut q = 0 ;
63+ //110 V=5+INT(35*RND(1))
64+ let v: f64 = 5.0 + 35.0 * rng. random_range ( 0.0 ..1.0 ) ;
65+ //111 PRINT "A BALL IS THROWN UPWARDS AT";V;"METERS PER SECOND."
66+ //112 PRINT
67+ print ! ( "\n A BALL IS THROWN UPWARDS AT {v:.2} METERS PER SECOND.\n " ) ;
68+ //115 A=.05*V^2
69+ //let a = 0.05 * v.powf(2.0); // OLD
70+ let mut a = v. powf ( 2.0 ) / ( 2.0 * 9.81 ) ; // NEW
71+ //116 PRINT "HOW HIGH WILL IT GO (IN METERS)";
72+ print ! ( "\n HOW HIGH WILL IT GO (IN METERS)? " ) ;
73+
74+ //117 GOSUB 500
75+ subroutine ( a, & mut q) ;
76+
77+ //120 A=V/5
78+ //a = v / 5.0; // OLD
79+ a = 2.0 * v / 9.81 ; // NEW
80+ //122 PRINT "HOW LONG UNTIL IT RETURNS (IN SECONDS)";
81+ print ! ( "\n HOW LONG UNTIL IT RETURNS (IN SECONDS)? " ) ;
82+ //124 GOSUB 500
83+ subroutine ( a, & mut q) ;
84+
85+ //130 T=1+INT(2*V*RND(1))/10
86+ let t = 1.0 + ( 2.0 * v * rng. random_range ( 0.0 ..1.0 ) / 10.0 ) ;
87+ //132 A=V-10*T
88+ a = v + ( -9.81 * t) ;
89+ //134 PRINT "WHAT WILL ITS VELOCITY BE AFTER";T;"SECONDS";
90+ print ! ( "\n WHAT WILL ITS VELOCITY BE AFTER {t:.2} SECONDS? " ) ;
91+
92+ //136 GOSUB 500
93+ subroutine ( a, & mut q) ;
94+
95+ //140 PRINT
96+ //150 PRINT Q;"RIGHT OUT OF 3.";
97+ print ! ( "\n {q} RIGHT OUT OF 3.\n " ) ;
98+ //160 IF Q<2 THEN 100
99+ if q < 2 {
100+ continue ;
101+ }
102+ //170 PRINT " NOT BAD."
103+ //print!(" NOT BAD.");
104+ //180 GOTO 100
105+ }
106+ //999 END
107+ }
0 commit comments