1 /*        $NetBSD: human.cc,v 1.4 2021/12/05 09:22:45 rillig Exp $    */
2 
3 /*-
4  * Copyright (c) 2003 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Christos Zoulas.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Human interface for dots, using rogue-like keys.
34  */
35 
36 #include "defs.h"
37 RCSID("$NetBSD: human.cc,v 1.4 2021/12/05 09:22:45 rillig Exp $")
38 
39 #include "human.h"
40 #include "board.h"
41 #include "box.h"
42 #include "ttyscrn.h"
43 
44 #define CONTROL(a) ((a) & 037)
45 
46 extern GAMESCREEN *sc;
47 
HUMAN(const char c)48 HUMAN::HUMAN(const char c) :
49     PLAYER(c),
50     _curx(0),
51     _cury(1)
52 {
53 }
54 
play(const BOARD & b,size_t & y,size_t & x,int & dir)55 void HUMAN::play(const BOARD& b, size_t& y, size_t& x, int& dir)
56 {
57     int mv;
58     b.setpos(_cury, _curx);
59 
60     for (;;) {
61           switch (mv = b.getmove()) {
62           case 'h': case 'H':
63               _curx -= 2;
64               break;
65 
66           case 'l': case 'L':
67               _curx += 2;
68               break;
69 
70           case 'k': case 'K':
71               _cury -= 2;
72               break;
73 
74           case 'j': case 'J':
75               _cury += 2;
76               break;
77 
78           case 'u': case 'U':
79               _curx += 1;
80               _cury -= 1;
81               break;
82 
83           case 'y': case 'Y':
84               _curx -= 1;
85               _cury -= 1;
86               break;
87 
88           case 'b': case 'B':
89               _curx -= 1;
90               _cury += 1;
91               break;
92 
93           case 'n': case 'N':
94               _curx += 1;
95               _cury += 1;
96               break;
97 
98           case 'q': case 'Q':
99               // Cleanup
100               delete sc;
101               exit(0);
102 
103           case CONTROL('L'): case CONTROL('R'):
104               b.clean();
105               b.paint();
106               break;
107 
108           case ' ':
109               {
110                     x = _curx / 2;
111                     y = _cury / 2;
112 
113                     if (_cury & 1) {
114                         if (_curx == 0)
115                               dir = BOX::left;
116                         else {
117                               x--;
118                               dir = BOX::right;
119                         }
120                     }
121 
122                     if (_curx & 1) {
123                         if (_cury == 0)
124                               dir = BOX::top;
125                         else {
126                               y--;
127                               dir = BOX::bottom;
128                         }
129                     }
130               }
131               return;
132 
133           default:
134               break;
135           }
136 
137         // We add 2 before the comparison to avoid underflow
138           if ((2 + _curx) - (_curx & 1) < 2)
139               _curx = (b.nx() * 2) + (_curx & 1);
140           if (_curx >= (b.nx() * 2) + 1)
141               _curx = (_curx & 1);
142 
143           if ((2 + _cury) - (_cury & 1) < 2)
144               _cury = (b.ny() * 2) + (_cury & 1);
145           if (_cury >= (b.ny() * 2) + 1)
146               _cury = (_cury & 1);
147 
148           b.setpos(_cury, _curx);
149     }
150 }
151