Bug Summary

File:src/games/mille/comp.c
Warning:line 235, column 6
Value stored to 'safe' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name comp.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/games/mille/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/games/mille/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/games/mille/comp.c
1/* $OpenBSD: comp.c,v 1.10 2016/01/08 18:09:59 mestre Exp $ */
2/* $NetBSD: comp.c,v 1.4 1995/03/24 05:01:11 cgd Exp $ */
3
4/*
5 * Copyright (c) 1982, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include "mille.h"
34
35/*
36 * @(#)comp.c 1.1 (Berkeley) 4/1/82
37 */
38
39# define V_VALUABLE40 40
40
41void
42calcmove(void)
43{
44 CARDshort card;
45 int *value;
46 PLAY *pp, *op;
47 bool_Bool foundend, cango, canstop, foundlow;
48 unsigned int i, count200, badcount, nummin, nummax, diff;
49 int curmin, curmax;
50 CARDshort safe, oppos;
51 int valbuf[HAND_SZ7], count[NUM_CARDS20];
52 bool_Bool playit[HAND_SZ7];
53
54 wmove(Score, ERR_Y15, ERR_X5); /* get rid of error messages */
55 wclrtoeol(Score);
56 pp = &Player[COMP1];
57 op = &Player[PLAYER0];
58 safe = 0;
59 cango = 0;
60 canstop = FALSE0;
61 foundend = FALSE0;
62
63 /* Try for a Coup Forre, and see what we have. */
64 for (i = 0; i < NUM_CARDS20; i++)
65 count[i] = 0;
66 for (i = 0; i < HAND_SZ7; i++) {
67 card = pp->hand[i];
68 switch (card) {
69 case C_STOP8: case C_CRASH7:
70 case C_FLAT6: case C_EMPTY5:
71 if ((playit[i] = canplay(pp, op, card)))
72 canstop = TRUE1;
73 goto norm;
74 case C_LIMIT9:
75 if ((playit[i] = canplay(pp, op, card))
76 && Numseen[C_250] == Numcards[C_250]
77 && Numseen[C_501] == Numcards[C_501])
78 canstop = TRUE1;
79 goto norm;
80 case C_250: case C_501: case C_752:
81 case C_1003: case C_2004:
82 if ((playit[i] = canplay(pp, op, card))
83 && pp->mileage + Value[card] == End)
84 foundend = TRUE1;
85 goto norm;
86 default:
87 playit[i] = canplay(pp, op, card);
88norm:
89 if (playit[i])
90 ++cango;
91 break;
92 case C_GAS_SAFE15: case C_DRIVE_SAFE17:
93 case C_SPARE_SAFE16: case C_RIGHT_WAY18:
94 if (pp->battle == opposite(card)(Opposite[card]) ||
95 (pp->speed == C_LIMIT9 && card == C_RIGHT_WAY18)) {
96 Movetype = M_PLAY2;
97 Card_no = i;
98 return;
99 }
100 ++safe;
101 playit[i] = TRUE1;
102 break;
103 }
104 if (card >= 0)
105 ++count[card];
106 }
107
108 /* No Coup Forre. Draw to fill hand, then restart, as needed. */
109 if (pp->hand[0] == C_INIT-1 && Topcard > Deck) {
110 Movetype = M_DRAW1;
111 return;
112 }
113
114#ifdef DEBUG
115 if (Debug)
116 fprintf(outf, "CALCMOVE: cango = %d, canstop = %d, safe = %d\n",
117 cango, canstop, safe);
118#endif
119 if (foundend)
120 foundend = !check_ext(TRUE1);
121 for (i = 0; safe && i < HAND_SZ7; i++) {
122 if (is_safety(pp->hand[i])(pp->hand[i] >= 15)) {
123 if (onecard(op) || (foundend && cango && !canstop)) {
124#ifdef DEBUG
125 if (Debug)
126 fprintf(outf,
127 "CALCMOVE: onecard(op) = %d, foundend = %d\n",
128 onecard(op), foundend);
129#endif
130playsafe:
131 Movetype = M_PLAY2;
132 Card_no = i;
133 return;
134 }
135 oppos = opposite(pp->hand[i])(Opposite[pp->hand[i]]);
136 if (Numseen[oppos] == Numcards[oppos] &&
137 !(pp->hand[i] == C_RIGHT_WAY18 &&
138 Numseen[C_LIMIT9] != Numcards[C_LIMIT9]))
139 goto playsafe;
140 else if (!cango
141 && (op->can_go || !pp->can_go || Topcard < Deck)) {
142 card = (Topcard - Deck) - roll(1, 10);
143 if ((!pp->mileage) != (!op->mileage))
144 card -= 7;
145#ifdef DEBUG
146 if (Debug)
147 fprintf(outf,
148 "CALCMOVE: card = %d, DECK_SZ / 4 = %d\n",
149 card, DECK_SZ101 / 4);
150#endif
151 if (card < DECK_SZ101 / 4)
152 goto playsafe;
153 }
154 safe--;
155 playit[i] = cango;
156 }
157 }
158 if (!pp->can_go && !is_repair(pp->battle))
159 Numneed[opposite(pp->battle)(Opposite[pp->battle])]++;
160redoit:
161 foundlow = (cango || count[C_END_LIMIT14] != 0
162 || Numseen[C_LIMIT9] == Numcards[C_LIMIT9]
163 || pp->safety[S_RIGHT_WAY3] != S_UNKNOWN0);
164 foundend = FALSE0;
165 count200 = pp->nummiles[C_2004];
166 badcount = 0;
167 curmax = -1;
168 curmin = 101;
169 nummin = -1;
170 nummax = -1;
171 value = valbuf;
172 for (i = 0; i < HAND_SZ7; i++) {
173 card = pp->hand[i];
174 if (is_safety(card)(card >= 15) || playit[i] == (cango != 0)) {
175#ifdef DEBUG
176 if (Debug)
177 fprintf(outf, "CALCMOVE: switch(\"%s\")\n",
178 C_name[card]);
179#endif
180 switch (card) {
181 case C_250: case C_501:
182 diff = End - pp->mileage;
183 /* avoid getting too close */
184 if (Topcard > Deck && cango && diff <= 100
185 && diff / Value[card] > count[card]
186 && (card == C_250 || diff % 50 == 0)) {
187 if (card == C_501 && diff - 50 == 25
188 && count[C_250] > 0)
189 goto okay;
190 *value = 0;
191 if (--cango <= 0)
192 goto redoit;
193 break;
194 }
195okay:
196 *value = (Value[card] >> 3);
197 if (pp->speed == C_LIMIT9)
198 ++*value;
199 else
200 --*value;
201 if (!foundlow
202 && (card == C_501 || count[C_501] == 0)) {
203 *value = (pp->mileage ? 10 : 20);
204 foundlow = TRUE1;
205 }
206 goto miles;
207 case C_2004:
208 if (++count200 > 2) {
209 *value = 0;
210 break;
211 }
212 case C_752: case C_1003:
213 *value = (Value[card] >> 3);
214 if (pp->speed == C_LIMIT9)
215 --*value;
216 else
217 ++*value;
218miles:
219 if (pp->mileage + Value[card] > End)
220 *value = (End == 700 ? card : 0);
221 else if (pp->mileage + Value[card] == End) {
222 *value = (foundend ? card : V_VALUABLE40);
223 foundend = TRUE1;
224 }
225 break;
226 case C_END_LIMIT14:
227 if (pp->safety[S_RIGHT_WAY3] != S_UNKNOWN0)
228 *value = (pp->safety[S_RIGHT_WAY3] ==
229 S_PLAYED2 ? -1 : 1);
230 else if (pp->speed == C_LIMIT9 &&
231 End - pp->mileage <= 50)
232 *value = 1;
233 else if (pp->speed == C_LIMIT9
234 || Numseen[C_LIMIT9] != Numcards[C_LIMIT9]) {
235 safe = S_RIGHT_WAY3;
Value stored to 'safe' is never read
236 oppos = C_LIMIT9;
237 goto repair;
238 }
239 else {
240 *value = 0;
241 --count[C_END_LIMIT14];
242 }
243 break;
244 case C_REPAIRS12: case C_SPARE11: case C_GAS10:
245 safe = safety(card) - S_CONV15;
246 oppos = opposite(card)(Opposite[card]);
247 if (pp->safety[safe] != S_UNKNOWN0)
248 *value = (pp->safety[safe] ==
249 S_PLAYED2 ? -1 : 1);
250 else if (pp->battle != oppos
251 && (Numseen[oppos] == Numcards[oppos] ||
252 Numseen[oppos] + count[card] >
253 Numcards[oppos])) {
254 *value = 0;
255 --count[card];
256 }
257 else {
258repair:
259 *value = Numcards[oppos] * 6;
260 *value += Numseen[card] -
261 Numseen[oppos];
262 if (!cango)
263 *value /= (count[card]*count[card]);
264 count[card]--;
265 }
266 break;
267 case C_GO13:
268 if (pp->safety[S_RIGHT_WAY3] != S_UNKNOWN0)
269 *value = (pp->safety[S_RIGHT_WAY3] ==
270 S_PLAYED2 ? -1 : 2);
271 else if (pp->can_go
272 && Numgos + count[C_GO13] == Numneed[C_GO13]) {
273 *value = 0;
274 --count[C_GO13];
275 }
276 else {
277 *value = Numneed[C_GO13] * 3;
278 *value += (Numseen[C_GO13] - Numgos);
279 *value /= (count[C_GO13] * count[C_GO13]);
280 count[C_GO13]--;
281 }
282 break;
283 case C_LIMIT9:
284 if (op->mileage + 50 >= End) {
285 *value = (End == 700 && !cango);
286 break;
287 }
288 if (canstop || (cango && !op->can_go))
289 *value = 1;
290 else {
291 *value = (pp->safety[S_RIGHT_WAY3] !=
292 S_UNKNOWN0 ? 2 : 3);
293 safe = S_RIGHT_WAY3;
294 oppos = C_END_LIMIT14;
295 goto normbad;
296 }
297 break;
298 case C_CRASH7: case C_EMPTY5: case C_FLAT6:
299 safe = safety(card) - S_CONV15;
300 oppos = opposite(card)(Opposite[card]);
301 *value = (pp->safety[safe]!=S_UNKNOWN0 ? 3 : 4);
302normbad:
303 if (op->safety[safe] == S_PLAYED2)
304 *value = -1;
305 else {
306 *value *= Numneed[oppos] +
307 Numseen[oppos] + 2;
308 if (!pp->mileage || foundend ||
309 onecard(op))
310 *value += 5;
311 if (op->mileage == 0 || onecard(op))
312 *value += 5;
313 if (op->speed == C_LIMIT9)
314 *value -= 3;
315 if (cango &&
316 pp->safety[safe] != S_UNKNOWN0)
317 *value += 3;
318 if (!cango)
319 *value /= ++badcount;
320 }
321 break;
322 case C_STOP8:
323 if (op->safety[S_RIGHT_WAY3] == S_PLAYED2)
324 *value = -1;
325 else {
326 *value = (pp->safety[S_RIGHT_WAY3] !=
327 S_UNKNOWN0 ? 3 : 4);
328 *value *= Numcards[C_STOP8] +
329 Numseen[C_GO13];
330 if (!pp->mileage || foundend ||
331 onecard(op))
332 *value += 5;
333 if (!cango)
334 *value /= ++badcount;
335 if (op->mileage == 0)
336 *value += 5;
337 if ((op->speed == C_LIMIT9) ||
338 !op->can_go)
339 *value -= 5;
340 if (cango && pp->safety[S_RIGHT_WAY3] !=
341 S_UNKNOWN0)
342 *value += 5;
343 }
344 break;
345 case C_GAS_SAFE15: case C_DRIVE_SAFE17:
346 case C_SPARE_SAFE16: case C_RIGHT_WAY18:
347 *value = cango ? 0 : 101;
348 break;
349 case C_INIT-1:
350 *value = 0;
351 break;
352 }
353 }
354 else
355 *value = cango ? 0 : 101;
356 if (card != C_INIT-1) {
357 if (*value >= curmax) {
358 nummax = i;
359 curmax = *value;
360 }
361 if (*value <= curmin) {
362 nummin = i;
363 curmin = *value;
364 }
365 }
366#ifdef DEBUG
367 if (Debug)
368 mvprintw(i + 6, 2, "%3d %-14s", *value,
369 C_name[pp->hand[i]]);
370#endif
371 value++;
372 }
373 if (!pp->can_go && !is_repair(pp->battle))
374 Numneed[opposite(pp->battle)(Opposite[pp->battle])]++;
375 if (cango) {
376play_it:
377 mvaddstr(MOVE_Y + 1, MOVE_X, "PLAY\n")(wmove(stdscr,10 + 1,20) == (-1) ? (-1) : waddnstr(stdscr,"PLAY\n"
,-1))
;
378 Movetype = M_PLAY2;
379 Card_no = nummax;
380 }
381 else {
382 if (is_safety(pp->hand[nummin])(pp->hand[nummin] >= 15)) { /* NEVER discard a safety */
383 nummax = nummin;
384 goto play_it;
385 }
386 mvaddstr(MOVE_Y + 1, MOVE_X, "DISCARD\n")(wmove(stdscr,10 + 1,20) == (-1) ? (-1) : waddnstr(stdscr,"DISCARD\n"
,-1))
;
387 Movetype = M_DISCARD0;
388 Card_no = nummin;
389 }
390 mvprintw(MOVE_Y10 + 2, MOVE_X20, "%16s", C_name[pp->hand[Card_no]]);
391}
392
393/*
394 * Return true if the given player could conceivably win with his next card.
395 */
396int
397onecard(const PLAY *pp)
398{
399 CARDshort bat, spd, card;
400
401 bat = pp->battle;
402 spd = pp->speed;
403 card = -1;
404 if (pp->can_go || ((is_repair(bat) || bat == C_STOP8 || spd == C_LIMIT9) &&
405 Numseen[S_RIGHT_WAY3] != 0) ||
406 (bat >= 0 && Numseen[safety(bat)] != 0))
407 switch (End - pp->mileage) {
408 case 200:
409 if (pp->nummiles[C_2004] == 2)
410 return FALSE0;
411 card = C_2004;
412 /* FALLTHROUGH */
413 case 100:
414 case 75:
415 if (card == -1)
416 card = (End - pp->mileage == 75 ? C_752 : C_1003);
417 if (spd == C_LIMIT9)
418 return Numseen[S_RIGHT_WAY3] == 0;
419 case 50:
420 case 25:
421 if (card == -1)
422 card = (End - pp->mileage == 25 ? C_250 : C_501);
423 return Numseen[card] != Numcards[card];
424 }
425 return FALSE0;
426}
427
428int
429canplay(const PLAY *pp, const PLAY *op, CARDshort card)
430{
431 switch (card) {
432 case C_2004:
433 if (pp->nummiles[C_2004] == 2)
434 break;
435 /* FALLTHROUGH */
436 case C_752: case C_1003:
437 if (pp->speed == C_LIMIT9)
438 break;
439 /* FALLTHROUGH */
440 case C_501:
441 if (pp->mileage + Value[card] > End)
442 break;
443 /* FALLTHROUGH */
444 case C_250:
445 if (pp->can_go)
446 return TRUE1;
447 break;
448 case C_EMPTY5: case C_FLAT6: case C_CRASH7:
449 case C_STOP8:
450 if (op->can_go && op->safety[safety(card) - S_CONV15] != S_PLAYED2)
451 return TRUE1;
452 break;
453 case C_LIMIT9:
454 if (op->speed != C_LIMIT9 &&
455 op->safety[S_RIGHT_WAY3] != S_PLAYED2 &&
456 op->mileage + 50 < End)
457 return TRUE1;
458 break;
459 case C_GAS10: case C_SPARE11: case C_REPAIRS12:
460 if (pp->battle == opposite(card)(Opposite[card]))
461 return TRUE1;
462 break;
463 case C_GO13:
464 if (!pp->can_go &&
465 (is_repair(pp->battle) || pp->battle == C_STOP8))
466 return TRUE1;
467 break;
468 case C_END_LIMIT14:
469 if (pp->speed == C_LIMIT9)
470 return TRUE1;
471 }
472 return FALSE0;
473}