File: decor.c

package info (click to toggle)
crossfire 1.75.0-9
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,168 kB
  • sloc: ansic: 83,169; sh: 4,659; perl: 1,736; lex: 1,443; makefile: 1,199; python: 43
file content (136 lines) | stat: -rw-r--r-- 3,983 bytes parent folder | download | duplicates (4)
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
/*
 * Crossfire -- cooperative multi-player graphical RPG and adventure game
 *
 * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
 * Copyright (c) 1992 Frank Tore Johansen
 *
 * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
 * welcome to redistribute it under certain conditions. For details, please
 * see COPYING and LICENSE.
 *
 * The authors can be reached via e-mail at <crossfire@metalforge.org>.
 */

/**
 * @file
 * Those functions handle the decor in the random maps.
 */

#include <assert.h>
#include <stdlib.h>

#include "global.h"
#include "random_map.h"
#include "rproto.h"

/** Number of decor styles that can be chosen if none specified. */
#define NR_DECOR_OPTIONS 1

/**
 * Count objects at a spot.
 * @param map
 * map we want to check
 * @param x
 * @param y
 * coordinates
 * @return
 * count of objects in the map at x,y.
 */
int obj_count_in_map(mapstruct *map, int x, int y)
{
    int count = 0;

    FOR_MAP_PREPARE(map, x, y, tmp)
    count++;
    FOR_MAP_FINISH();
    return count;
}

/**
 * Put the decor into the map.  Right now, it's very primitive.
 * @param map
 * map to add decor to.
 * @param maze
 * layout of the map, as was generated.
 * @param decorstyle
 * style to use. Can be NULL.
 * @param decor_option
 * how to place decor:
 * - 0 means no decor.
 * - 1 means to place randomly decor.
 * - other means to fill the map with decor.
 * @param RP
 * parameters of the random map.
 */
void put_decor(mapstruct *map, char **maze, char *decorstyle, int decor_option, RMParms *RP)
{
    mapstruct *decor_map;

    decor_map = find_style("/styles/decorstyles", decorstyle, -1);
    if (decor_map == NULL) {
        return;
    }

    /* pick a random option, only 1 option right now. */
    if (decor_option == 0) {
        decor_option = RANDOM()%NR_DECOR_OPTIONS+1;
    }

    assert(decor_option != 0);

    switch (decor_option) {
    case 1: { /* random placement of decor objects. */
        int number_to_place = RANDOM()%((RP->Xsize*RP->Ysize)/5);
        int failures = 0;
        object *new_decor_object;

        while (failures < 100 && number_to_place > 0) {
            int x, y;

            x = RANDOM()%(RP->Xsize-2)+1;
            y = RANDOM()%(RP->Ysize-2)+1;
            if (maze[x][y] == 0 && obj_count_in_map(map, x, y) < 2) { /* empty */
                object *this_object;

                new_decor_object = pick_random_object(decor_map);
                this_object = arch_to_object(new_decor_object->arch);
                object_copy(new_decor_object, this_object);
                /*
                 * Don't change move_block, this prevents item merging.
                 * Instead, fix the item on the style map if blocking
                 * is bad.
                 */
                /*this_object->move_block = MOVE_BLOCK_DEFAULT;*/
                object_insert_in_map_at(this_object, map, NULL, 0, x, y);
                number_to_place--;
            } else {
                failures++;
            }
        }
        break;
    }

    default: { /* place decor objects everywhere: tile the map. */
        int i, j;

        for (i = 1; i < RP->Xsize-1; i++)
            for (j = 1; j < RP->Ysize-1; j++) {
                if (maze[i][j] == 0) {
                    object *new_decor_object, *this_object;

                    new_decor_object = pick_random_object(decor_map);
                    this_object = arch_to_object(new_decor_object->arch);
                    object_copy(new_decor_object, this_object);
                    /*
                     * Don't change move_block, this prevents item merging.
                     * Instead, fix the item on the style map if blocking
                     * is bad.
                     */
                    /*this_object->move_block = MOVE_BLOCK_DEFAULT;*/
                    object_insert_in_map_at(this_object, map, NULL, 0, i, j);
                }
            }
        break;
    }
    }
}