forked from sneezymud/dikumud
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathboard.c
341 lines (286 loc) · 9.27 KB
/
board.c
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "utils.h"
#include "structs.h"
#include "comm.h"
#define MAX_MSGS 50 /* Max number of messages. */
#define SAVE_FILE "board.messages" /* Name of file for saving messages */
#define BOARD_OBJECT xxx /* what are we? */
#define BOARD_ROOM xxx /* where are we? */
#define MAX_MESSAGE_LENGTH 4000 /* that should be enough */
char *msgs[MAX_MSGS];
char *head[MAX_MSGS];
int msg_num;
void board_write_msg(struct char_data *ch, char *arg);
int board_display_msg(struct char_data *ch, char *arg);
int board_remove_msg(struct char_data *ch, char *arg);
void board_save_board();
void board_load_board();
void board_reset_board();
void error_log();
void board_fix_long_desc(int num, char *headers[MAX_MSGS]);
int board_show_board(struct char_data *ch, char *arg);
/* I have used cmd number 180-182 as the cmd numbers here. */
/* The commands would be, in order : NOTE <header> */
/* READ <message number>, REMOVE <message number> */
/* LOOK AT BOARD should give the long desc of the board */
/* and that should equal a list of message numbers and */
/* headers. This is done by calling a function that sets */
/* the long desc in the board object. This function is */
/* called when someone does a REMOVE or NOTE command. */
/* I have named the function board_fix_long_desc(). In the */
/* board_write_msg() function there is a part that should */
/* be replaced with a call to some dreadful routine used */
/* by the STRING command to receive player input. It is */
/* reputed to lurk somewhere within the limits of an evil */
/* file named act.comm.c.....*/
/* saving the board after the addition of a new messg */
/* poses a slight problem, since the text isn't actually */
/* entered in board_write. What I'll do is to let board() */
/* save the first time a 'look' is issued in the room.. */
/* ugh! that's ugly - gotta think of something better. */
/* -quinn */
/* And here is the board...correct me if I'm wrong. */
int board(struct char_data *ch, int cmd, char *arg)
{
static int has_loaded = 0;
if (!ch->desc)
return(FALSE); /* By MS or all NPC's will be trapped at the board */
/* note: I'll let display and remove return 0 if the arg was non-board- */
/* related. Thus, it'll be possible to read other things than the board */
/* while you're in the room. Conceiveably, you could do this for write, */
/* too, but I'm not in the mood for such hacking. */
if (!has_loaded)
{
board_load_board();
has_loaded = 1;
}
switch (cmd) {
case 15: /* look */
return(board_show_board(ch, arg));
case 149: /* write */
board_write_msg(ch, arg);
return 1;
case 63: /* read */
return(board_display_msg(ch, arg));
case 66: /* remove */
return(board_remove_msg(ch, arg));
default:
return 0;
}
}
void board_write_msg(struct char_data *ch, char *arg) {
if (msg_num > MAX_MSGS - 1) {
send_to_char("The board is full already.\n\r", ch);
return;
}
/* skip blanks */
for(; isspace(*arg); arg++);
if (!*arg) {
send_to_char("We must have a headline!\n\r", ch);
return;
}
head[msg_num] = (char *)malloc(strlen(arg) + strlen(GET_NAME(ch)) + 4);
/* +4 is for a space and '()' around the character name. */
if (!head[msg_num]) {
error_log("Malloc for board header failed.\n\r");
send_to_char("The board is malfunctioning - sorry.\n\r", ch);
return;
}
strcpy(head[msg_num], arg);
/* Is this clumsy? - four strcat() in a row I mean..*/
strcat(head[msg_num], " (");
strcat(head[msg_num], GET_NAME(ch));
strcat(head[msg_num], ")");
msgs[msg_num] = NULL;
send_to_char("Write your message. Terminate with a @.\n\r\n\r", ch);
act("$n starts to write a message.", TRUE, ch, 0, 0, TO_ROOM);
ch->desc->str = &msgs[msg_num];
ch->desc->max_str = MAX_MESSAGE_LENGTH;
msg_num++;
}
int board_remove_msg(struct char_data *ch, char *arg) {
int ind, msg;
char buf[256], number[MAX_INPUT_LENGTH];
if (GET_LEVEL(ch) < 10) {
send_to_char("Due to misuse of the REMOVE command, only 10th level\n\r", ch);
send_to_char("and above can remove messages.\n\r", ch);
return;
}
one_argument(arg, number);
if (!*number || !isdigit(*number))
return(0);
if (!(msg = atoi(number))) return(0);
if (!msg_num) {
send_to_char("The board is empty!\n\r", ch);
return(1);
}
if (msg < 1 || msg > msg_num) {
send_to_char("That message exists only in your imagination..\n\r",
ch);
return(1);
}
ind = msg;
free(head[--ind]);
if (msgs[ind])
free(msgs[ind]);
for (; ind < msg_num -1; ind++) {
head[ind] = head[ind + 1];
msgs[ind] = msgs[ind + 1];
}
msg_num--;
send_to_char("Message removed.\n\r", ch);
sprintf(buf, "$n just removed message %d.", ind + 1);
act(buf, FALSE, ch, 0, 0, TO_ROOM);
board_save_board();
return(1);
}
void board_save_board() {
FILE *the_file;
int ind, len;
if (!msg_num) {
error_log("No messages to save.\n\r");
return;
}
the_file = fopen(SAVE_FILE, "wb");
if (!the_file) {
error_log("Unable to open/create savefile..\n\r");
return;
}
fwrite(&msg_num, sizeof(int), 1, the_file);
for (ind = 0; ind < msg_num; ind++) {
len = strlen(head[ind]) + 1;
fwrite(&len, sizeof(int), 1, the_file);
fwrite(head[ind], sizeof(char), len, the_file);
len = strlen(msgs[ind]) + 1;
fwrite(&len, sizeof(int), 1, the_file);
fwrite(msgs[ind], sizeof(char), len, the_file);
}
fclose(the_file);
board_fix_long_desc(msg_num, head);
return;
}
void board_load_board() {
FILE *the_file;
int ind, len = 0;
board_reset_board();
the_file = fopen(SAVE_FILE, "rb");
if (!the_file) {
error_log("Can't open message file. Board will be empty.\n\r",0);
return;
}
fread(&msg_num, sizeof(int), 1, the_file);
if (msg_num < 1 || msg_num > MAX_MSGS || feof(the_file)) {
error_log("Board-message file corrupt or nonexistent.\n\r");
fclose(the_file);
return;
}
for (ind = 0; ind < msg_num; ind++) {
fread(&len, sizeof(int), 1, the_file);
head[ind] = (char *)malloc(len + 1);
if (!head[ind]) {
error_log("Malloc for board header failed.\n\r");
board_reset_board();
fclose(the_file);
return;
}
fread(head[ind], sizeof(char), len, the_file);
fread(&len, sizeof(int), 1, the_file);
msgs[ind] = (char *)malloc(len + 1);
if (!msgs[ind]) {
error_log("Malloc for board msg failed..\n\r");
board_reset_board();
fclose(the_file);
return;
}
fread(msgs[ind], sizeof(char), len, the_file);
}
fclose(the_file);
board_fix_long_desc(msg_num, head);
return;
}
void board_reset_board() {
int ind;
for (ind = 0; ind < MAX_MSGS; ind++) {
free(head[ind]);
free(msgs[ind]);
}
msg_num = 0;
board_fix_long_desc(0, 0);
return;
}
void error_log(char *str) { /* The original error-handling was MUCH */
fputs("Board : ", stderr); /* more competent than the current but */
fputs(str, stderr); /* I got the advice to cut it out..;) */
return;
}
int board_display_msg(struct char_data *ch, char *arg) {
char buf[512], number[MAX_INPUT_LENGTH], buffer[MAX_STRING_LENGTH];
int msg;
one_argument(arg, number);
if (!*number || !isdigit(*number))
return(0);
if (!(msg = atoi(number))) return(0);
if (!msg_num) {
send_to_char("The board is empty!\n\r", ch);
return(1);
}
if (msg < 1 || msg > msg_num) {
send_to_char("That message exists only in your imagination..\n\r",
ch);
return(1);
}
/* sprintf(buf, "$n reads message %d titled : %s.",
msg, head[msg - 1]);
act(buf, TRUE, ch, 0, 0, TO_ROOM); */
/* Can PERFORM() handle this...? no. Sorry*/
/* sprintf(ch, "Message %d : %s\n\r%s", msg, head[msg - 1], msgs[msg - 1]); */
/* Bad news */
sprintf(buffer, "Message %d : %s\n\r\n\r%s", msg, head[msg - 1],
msgs[msg - 1]);
page_string(ch->desc, buffer, 1);
return(1);
}
void board_fix_long_desc(int num, char *headers[MAX_MSGS]) {
struct obj_data *ob;
/**** Assign the right value to this pointer..how? ****/
/**** It should point to the bulletin board object ****/
/**** Then make ob.description point to a malloced ****/
/**** space containing itoa(msg_num) and all the ****/
/**** headers. In the format :
This is a bulletin board. Usage : READ/REMOVE <message #>, NOTE <header>
There are 12 messages on the board.
1 : Re : Whatever and something else too.
2 : I don't agree with Rainbird.
3 : Me neither.
4 : Groo got hungry again - bug or sabotage?
Well...something like that..;) ****/
/**** It is always to contain the first line and ****/
/**** the second line will vary in how many notes ****/
/**** the board has. Then the headers and message ****/
/**** numbers will be listed. ****/
return;
}
int board_show_board(struct char_data *ch, char *arg)
{
int i;
char buf[MAX_STRING_LENGTH], tmp[MAX_INPUT_LENGTH];
one_argument(arg, tmp);
if (!*tmp || !isname(tmp, "board bulletin"))
return(0);
act("$n studies the board.", TRUE, ch, 0, 0, TO_ROOM);
strcpy(buf,
"This is a bulletin board. Usage: READ/REMOVE <messg #>, WRITE <header>\n\r");
if (!msg_num)
strcat(buf, "The board is empty.\n\r");
else
{
sprintf(buf + strlen(buf), "There are %d messages on the board.\n\r",
msg_num);
for (i = 0; i < msg_num; i++)
sprintf(buf + strlen(buf), "%-2d : %s\n\r", i + 1, head[i]);
}
page_string(ch->desc, buf, 1);
return(1);
}