Wumpus Hunt

Stroustrup has an exercise in which the reader writes a program for the wumpus hunt game. A first draft of my code is below. It compiles and runs partly correctly. If you choose to move to a different room the program runs as expected. If you choose to shoot at the wumpus, I get something called run-time error #3. It seems that the room I call 'current' is being perceived as a variable. The error description is that the variable 'current' is not initialized.

I don't understand that error because the 'current' room variables are not used in the lines in question.

Here is my code. It is not a final version.
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#include "../../std_lib_facilities.h"

class Room {
public:
	double rand_wumpus;
	double rand_pit;
	double rand_bat;
	bool wumpus_in_room;
	bool pit_in_room;
	bool bat_in_room;
	int room_num;
};

int main() {
cout << "You are safe and in room 100!" << endl;

for (int i = 0; i < 5; i++) {
Room adjacent1;
    srand((unsigned)time(0));
    adjacent1.room_num = 120;
    adjacent1.rand_wumpus = 100.0 * rand()/RAND_MAX;
    adjacent1.rand_pit = 100.0 * rand()/RAND_MAX;
    adjacent1.rand_bat = 100.0 * rand()/RAND_MAX;

    if (adjacent1.rand_wumpus > 30.1 && adjacent1.rand_wumpus < 47.8) {
		adjacent1.wumpus_in_room = true;
	} else {
		adjacent1.wumpus_in_room = false;
	}

    if (adjacent1.rand_pit > 83.1 && adjacent1.rand_pit < 95.5) {
		adjacent1.pit_in_room = true;
	} else {
		adjacent1.pit_in_room = false;
	}

	if (adjacent1.rand_bat > 22.7 && adjacent1.rand_bat < 40.4) {
		adjacent1.bat_in_room = true;
	} else {
		adjacent1.bat_in_room = false;
	}

Room adjacent2;
    srand((unsigned)time(0));
    adjacent2.room_num = 150;
    adjacent2.rand_wumpus = 100.0 * rand()/RAND_MAX;
    adjacent2.rand_pit = 100.0 * rand()/RAND_MAX;
    adjacent2.rand_bat = 100.0 * rand()/RAND_MAX;

    if (adjacent2.rand_wumpus > 56.0 && adjacent2.rand_wumpus < 68.3) {
		adjacent2.wumpus_in_room = true;
	} else {
		adjacent2.wumpus_in_room = false;
	}

    if (adjacent2.rand_pit > 5.8 && adjacent2.rand_pit < 22.4) {
		adjacent2.pit_in_room = true;
	} else {
		adjacent2.pit_in_room = false;
	}

	if (adjacent2.rand_bat > 28.2 && adjacent2.rand_bat < 46.5) {
		adjacent2.bat_in_room = true;
	} else {
		adjacent2.bat_in_room = false;
	}

Room adjacent3;
    srand((unsigned)time(0));
    adjacent3.room_num = 160;
    adjacent3.rand_wumpus = 100.0 * rand()/RAND_MAX;
    adjacent3.rand_pit = 100.0 * rand()/RAND_MAX;
    adjacent3.rand_bat = 100.0 * rand()/RAND_MAX;

    if (adjacent3.rand_wumpus > 52.3 && adjacent3.rand_wumpus < 75.7) {
		adjacent3.wumpus_in_room = true;
	} else {
		adjacent3.wumpus_in_room = false;
	}

    if (adjacent3.rand_pit > 57.4 && adjacent3.rand_pit < 75.2) {
		adjacent3.pit_in_room = true;
	} else {
		adjacent3.pit_in_room = false;
	}

    if (adjacent3.rand_bat > 44.9 && adjacent3.rand_bat < 60.2) {
		adjacent3.bat_in_room = true;
	} else {
		adjacent3.bat_in_room = false;
	}

Room current;
    cout << "There are passage ways to rooms " << adjacent1.room_num <<", " << adjacent2.room_num <<", and " << adjacent3.room_num <<"." << endl;

    if (adjacent1.wumpus_in_room == true || adjacent2.wumpus_in_room == true || adjacent3.wumpus_in_room == true) {
		cout << "I smell the wumpus." << endl;
	}

    if (adjacent1.pit_in_room == true || adjacent2.pit_in_room == true || adjacent3.pit_in_room == true) {
		cout << "I feel a breeze." << endl;
	}

	if (adjacent1.bat_in_room == true || adjacent2.bat_in_room == true || adjacent3.bat_in_room == true) {
		cout << "I hear a bat." << endl;
	}

    cout << endl;
    cout << "Do you wish to move or shoot?" << endl;

    string play = " ";
    cin >> play;

	srand((unsigned)time(0));
	double prob_wumpus = rand()/RAND_MAX;

	if (play == "s120") {
		if (adjacent1.wumpus_in_room == true) {
			cout << "You shot the wumpus!  YOU WIN!!!" << endl;
		}
	    if (adjacent1.wumpus_in_room == false) {
		    if (prob_wumpus <= 0.70) {
			    cout << "You missed the wumpus.  Play again." << endl;
		    }
		    if (prob_wumpus > 0.70) {
			    cout << "You missed the wumpus.  It has come into your room and eaten you!" << endl;
	            }
	    }
	}

	if (play == "s150") {
		if (adjacent1.wumpus_in_room == true) {
			cout << "You shot the wumpus!  YOU WIN!!!" << endl;
		}
	    if (adjacent1.wumpus_in_room == false) {
		    if (prob_wumpus <= 0.50) {
			    cout << "You missed the wumpus.  Play again." << endl;
		    }
		    if (prob_wumpus > 0.50) {
			    cout << "You missed the wumpus.  It has come into your room and eaten you!" << endl;
	            }
	    }
	}

	if (play == "s160") {
		if (adjacent1.wumpus_in_room == true) {
			cout << "You shot the wumpus!  YOU WIN!!!" << endl;
		}
	    if (adjacent1.wumpus_in_room == false) {
		    if (prob_wumpus <= 0.60) {
			    cout << "You missed the wumpus.  Play again." << endl;
		    }
		    if (prob_wumpus > 0.60) {
			    cout << "You missed the wumpus.  It has come into your room and eaten you!" << endl;
	            }
	    }
	}

	if (play == "m120") {
		current.room_num = 120;
		current.wumpus_in_room = adjacent1.wumpus_in_room;
		current.pit_in_room = adjacent1.pit_in_room;
		current.bat_in_room = adjacent1.bat_in_room;
	}

	if (play == "m150") {
		current.room_num = 150;
		current.wumpus_in_room = adjacent2.wumpus_in_room;
		current.pit_in_room = adjacent2.pit_in_room;
		current.bat_in_room = adjacent2.bat_in_room;
	}

	if (play == "m160") {
		current.room_num = 160;
		current.wumpus_in_room = adjacent3.wumpus_in_room;
		current.pit_in_room = adjacent3.pit_in_room;
		current.bat_in_room = adjacent3.bat_in_room;
	}

	if (current.wumpus_in_room == true) {cout << "The wumpus is in the room.  You are eaten!" << endl;} 
	
	if (current.pit_in_room == true) {cout << "You have fallen into a pit and died!" << endl;}

	if (current.bat_in_room == true) {cout << "A bat has taken you to another room!" << endl;}

	if (current.wumpus_in_room == false && current.pit_in_room == false && current.bat_in_room == false) {
		cout << "You are safe and in room " << current.room_num <<"!" << endl;
	}
}

	keep_window_open();
        return 0;
}


Please explain the error to me and whether I am close to or far from the right track for this game. Thanks in advance.
1. Room is a really a structure, not a class. It doesn't have any constructors, so its members remain uninitialised until they're explicity assigned values. current is only assigned values if the user enters m160, m150 or m120.

2. Don't keep calling srand((unsigned)time(0));. Calling it once at the top of the program will suffice.

3. rand() returns an int. So expression rand()/RAND_MAX is zero. You get away with it sometimes where you use 100.0 * rand()/RAND_MAX as the 100 is a double, the whole expression gets promoted to a double, but you get could out on line 115.

4. Indentation is important. Choose a style and stick to it or you'll never be able to read your own code.
Also, you should not write if (x==true) or if (x==false) - that's redundant. When wording it out, it says "if it is true that x is true...". Instead you should just write if (x) and if (!x), respectively.
And when you have just one statement after an if or else, you can and should omit the braces - especially if you would have put them on the same line anyway.
Change line 93 to this. Room current = {0};
Or combine those consecutive if clauses into one big if...else if... else.
Why do this?

Because the variable remains unset should all the if clauses you have put in your code fail. Therefore resulting in segmentation fault when attempting to read it. Your compiler is clever and thus warns you of this. Wherefore, adding a final "else" clause or initialising the variable at the start shall solve this problem.

@Athar.
Not to sound rude but you are incorrect.
if (x) and if (x == true) compiles to the same assembly code in nearly every compiler. if (x) translates to if (x != 0).
It is merely a matter of choice which one to use.

It is also not absolutely required that you always omit the braces, sometimes the code is more readable if the braces remain.
Although the OPs way of indentation is not at all reader-friendly.
Last edited on
Room current = {0}; does not initialise current.
It initialises all members of current to 0.

It is extremely useful for initialising every member without knowing it's type. Strings, pointers, integers all shall be set to '\0', NULL and 0 respectively.
Last edited on
You mean C strings, not C++ strings.
unoriginal You seem to be right, but I can't find where that's stated in the C standard.
Thank you for the comments. I changed Room from class to struct and I call srand() just once.

I have a reply about the indentation. I do not totally control it. The IDE I use, VC++, indents automatically. I copy/paste code to this forum. That process changes the indentation from what VC++ created. I try to undo those changes but for long code it is too tedious and time consuming.

I found the error to my original question. I believe unoriginal is correct, if I understand him correctly. The error was that when the player chooses to shoot, the code on lines 159 through 178 (above, not below) are not executed. This results in an error because those are the lines in which the current.variables are declared a initialized. I added a conditional to by-pass those lines when the player shoots instead of moves to an adjacent room.

The question I have now relates to the loop I am trying to make. For testing purposes I used a for loop, but the game needs a while loop. When I try to implement a while loop using a flag to indicate when the loop should end, the program goes straight to the end. It does not enter or execute the loop at all. The flag code is commented out in this version.

I would rather that the program go directly to the "Game Over" line immediately when the flag is set to 1, but first things first.

Here is the revised code. I apologize in advance for the reader-unfriendly indentation.
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#include "../../std_lib_facilities.h"

struct Room {
	double rand_wumpus;
	double rand_pit;
	double rand_bat;
	bool wumpus_in_room;
	bool pit_in_room;
	bool bat_in_room;
	int room_num;

};

int main() {
//int flag = 0;
cout << "You are safe and in room 100!" << endl;
srand((unsigned)time(0));

for (int i = 0; i < 5; i++) {
//while (flag = 0) {
Room adjacent1;
	adjacent1.room_num = 120;
    adjacent1.rand_wumpus = 100.0 * rand()/RAND_MAX;
    adjacent1.rand_pit = 100.0 * rand()/RAND_MAX;
    adjacent1.rand_bat = 100.0 * rand()/RAND_MAX;

    if (adjacent1.rand_wumpus > 30.1 && adjacent1.rand_wumpus < 47.8) {
		adjacent1.wumpus_in_room = true;
	} else {
		adjacent1.wumpus_in_room = false;
	}

    if (adjacent1.rand_pit > 83.1 && adjacent1.rand_pit < 95.5) {
		adjacent1.pit_in_room = true;
	} else {
		adjacent1.pit_in_room = false;
	}

	if (adjacent1.rand_bat > 22.7 && adjacent1.rand_bat < 40.4) {
		adjacent1.bat_in_room = true;
	} else {
		adjacent1.bat_in_room = false;
	}

Room adjacent2;
	adjacent2.room_num = 150;
    adjacent2.rand_wumpus = 100.0 * rand()/RAND_MAX;
    adjacent2.rand_pit = 100.0 * rand()/RAND_MAX;
    adjacent2.rand_bat = 100.0 * rand()/RAND_MAX;

    if (adjacent2.rand_wumpus > 56.0 && adjacent2.rand_wumpus < 68.3) {
		adjacent2.wumpus_in_room = true;
	} else {
		adjacent2.wumpus_in_room = false;
	}

    if (adjacent2.rand_pit > 5.8 && adjacent2.rand_pit < 22.4) {
		adjacent2.pit_in_room = true;
	} else {
		adjacent2.pit_in_room = false;
	}

	if (adjacent2.rand_bat > 28.2 && adjacent2.rand_bat < 46.5) {
		adjacent2.bat_in_room = true;
	} else {
		adjacent2.bat_in_room = false;
	}

Room adjacent3;
	adjacent3.room_num = 160;
    adjacent3.rand_wumpus = 100.0 * rand()/RAND_MAX;
    adjacent3.rand_pit = 100.0 * rand()/RAND_MAX;
    adjacent3.rand_bat = 100.0 * rand()/RAND_MAX;

    if (adjacent3.rand_wumpus > 52.3 && adjacent3.rand_wumpus < 75.7) {
		adjacent3.wumpus_in_room = true;
	} else {
		adjacent3.wumpus_in_room = false;
	}

    if (adjacent3.rand_pit > 57.4 && adjacent3.rand_pit < 75.2) {
		adjacent3.pit_in_room = true;
	} else {
		adjacent3.pit_in_room = false;
	}

    if (adjacent3.rand_bat > 44.9 && adjacent3.rand_bat < 60.2) {
		adjacent3.bat_in_room = true;
	} else {
		adjacent3.bat_in_room = false;
	}

Room current;
	cout << "There are passage ways to rooms " << adjacent1.room_num <<", " << adjacent2.room_num <<", and " << adjacent3.room_num <<"." << endl;

    if (adjacent1.wumpus_in_room == true || adjacent2.wumpus_in_room == true || adjacent3.wumpus_in_room == true) {
		cout << "I smell the wumpus." << endl;
	}

    if (adjacent1.pit_in_room == true || adjacent2.pit_in_room == true || adjacent3.pit_in_room == true) {
		cout << "I feel a breeze." << endl;
	}

	if (adjacent1.bat_in_room == true || adjacent2.bat_in_room == true || adjacent3.bat_in_room == true) {
		cout << "I hear a bat." << endl;
	}

    cout << endl;
    cout << "Do you wish to move or shoot?" << endl;

    string play = " ";
    cin >> play;

	srand((unsigned)time(0));
	double prob_wumpus = rand()/RAND_MAX;

	if (play == "s120") {
		if (adjacent1.wumpus_in_room == true) {
			cout << "You shot the wumpus!  YOU WIN!!!" << endl;
//			flag = 1;
		}
	    if (adjacent1.wumpus_in_room == false) {
		    if (prob_wumpus <= 0.70) {
			    cout << "You missed the wumpus.  Play again." << endl;
		    }
		    if (prob_wumpus > 0.70) {
			    cout << "You missed the wumpus.  It has come into your room and eaten you!" << endl;
//			    flag = 1;
	        }
		}
	}

	if (play == "s150") {
		if (adjacent1.wumpus_in_room == true) {
			cout << "You shot the wumpus!  YOU WIN!!!" << endl;
//			flag = 1;
		}
	    if (adjacent1.wumpus_in_room == false) {
		    if (prob_wumpus <= 0.50) {
			    cout << "You missed the wumpus.  Play again." << endl;
		    }
		    if (prob_wumpus > 0.50) {
			    cout << "You missed the wumpus.  It has come into your room and eaten you!" << endl;
//			    flag = 1;
	        }
		}
	}

	if (play == "s160") {
		if (adjacent1.wumpus_in_room == true) {
			cout << "You shot the wumpus!  YOU WIN!!!" << endl;
//			flag = 1;
		}
	    if (adjacent1.wumpus_in_room == false) {
		    if (prob_wumpus <= 0.60) {
			    cout << "You missed the wumpus.  Play again." << endl;
		    }
		    if (prob_wumpus > 0.60) {
			    cout << "You missed the wumpus.  It has come into your room and eaten you!" << endl;
//			    flag = 1;
	        }
		}
	}

	if (play == "m120") {
		current.room_num = 120;
		current.wumpus_in_room = adjacent1.wumpus_in_room;
		current.pit_in_room = adjacent1.pit_in_room;
		current.bat_in_room = adjacent1.bat_in_room;
	}

	if (play == "m150") {
		current.room_num = 150;
		current.wumpus_in_room = adjacent2.wumpus_in_room;
		current.pit_in_room = adjacent2.pit_in_room;
		current.bat_in_room = adjacent2.bat_in_room;
	}

	if (play == "m160") {
		current.room_num = 160;
		current.wumpus_in_room = adjacent3.wumpus_in_room;
		current.pit_in_room = adjacent3.pit_in_room;
		current.bat_in_room = adjacent3.bat_in_room;
	}

	if (play == "m120" || play == "m150" || play == "m160") {
	if (current.wumpus_in_room == true) {
		cout << "The wumpus is in the room.  You are eaten!" << endl;
//		flag = 1;
	} 
	
	if (current.pit_in_room == true) {
		cout << "You have fallen into a pit and died!" << endl;
//		flag = 1;
	}

	if (current.bat_in_room == true) {cout << "A bat has taken you to another room!" << endl;}

	if (current.wumpus_in_room == false && current.pit_in_room == false && current.bat_in_room == false) {
		cout << "You are safe and in room " << current.room_num <<"!" << endl;
	}
	}
}
    cout << "Game Over." << endl;

	keep_window_open();
    return 0;
}
Stupid me! Nevermind. I just noticed that line 20 should be while (flag == 0).
I am marking this thread as solved. The next adjustments are major revisions. For example, I need to randomize the adjacent rooms. When I have gone as far as I can with that, I will ask for comments in a new thread.
unoriginal wrote:
@Athar.
Not to sound rude but you are incorrect.

No.

unoriginal wrote:
if (x) and if (x == true) compiles to the same assembly code in nearly every compiler.

...which is exactly my point.
Topic archived. No new replies allowed.