1 /*
2  * Copyright (C) 2004 Ivo Danihelka (ivo@danihelka.net)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  */
9 #include "ModelFactory.h"
10 
11 #include "V2.h"
12 #include "Unit.h"
13 #include "Shape.h"
14 #include "LogicException.h"
15 #include "StringTool.h"
16 
17 //-----------------------------------------------------------------
18 /**
19  * Add model at scene.
20  * @param kind kind of item (e.g. "fish_big", "item_light", ...)
21  * @param loc placement location
22  * @param shape see Shape for format
23  * @return model
24  *
25  * @throws LogicException for unknown kind
26  * @throws LayoutException when shape or location is bad
27  */
28 Cube *
createModel(const std::string & kind,const V2 & loc,const std::string & shape)29 ModelFactory::createModel(const std::string &kind, const V2 &loc,
30         const std::string &shape)
31 {
32     if (StringTool::startsWith(kind, "output_")) {
33         return createOutputItem(kind, loc, shape);
34     }
35 
36     Cube::eWeight weight;
37     Cube::eWeight power;
38     bool alive;
39     createParams(kind, &weight, &power, &alive);
40 
41     Shape *newShape = new Shape(shape);
42     Cube *model = new Cube(loc,
43             weight, power, alive, newShape);
44 
45     return model;
46 }
47 //-----------------------------------------------------------------
48 /**
49  * Determine object params.
50  * @throws LogicException when kind is unkown
51  */
52 void
createParams(const std::string & kind,Cube::eWeight * out_weight,Cube::eWeight * out_power,bool * out_alive)53 ModelFactory::createParams(const std::string &kind,
54         Cube::eWeight *out_weight, Cube::eWeight *out_power, bool *out_alive)
55 {
56     if ("fish_small" == kind) {
57         *out_weight = Cube::LIGHT;
58         *out_power = Cube::LIGHT;
59         *out_alive = true;
60     }
61     else if ("fish_big" == kind) {
62         *out_weight = Cube::LIGHT;
63         *out_power = Cube::HEAVY;
64         *out_alive = true;
65     }
66     else if (StringTool::startsWith(kind, "fish_extra")) {
67         *out_weight = Cube::LIGHT;
68         *out_power = Cube::LIGHT;
69         *out_alive = true;
70     }
71     else if (StringTool::startsWith(kind, "fish_EXTRA")) {
72         *out_weight = Cube::LIGHT;
73         *out_power = Cube::HEAVY;
74         *out_alive = true;
75     }
76     else {
77         *out_power = Cube::NONE;
78         *out_alive = false;
79         if ("item_light" == kind) {
80             *out_weight = Cube::LIGHT;
81         }
82         else if ("item_heavy" == kind) {
83             *out_weight = Cube::HEAVY;
84         }
85         else if ("item_fixed" == kind) {
86             *out_weight = Cube::FIXED;
87         }
88         else {
89             throw LogicException(ExInfo("unknown model kind")
90                     .addInfo("kind", kind));
91         }
92     }
93 }
94 //-----------------------------------------------------------------
95 /**
96  * Create unit for driveable fish.
97  * @param kind kind of item (e.g. "fish_big", "item_light", ...)
98  * @return new unit or NULL
99  */
100 Unit *
createUnit(const std::string & kind)101 ModelFactory::createUnit(const std::string &kind)
102 {
103     Unit *result = NULL;
104     if ("fish_small" == kind) {
105         KeyControl smallfish;
106         smallfish.setUp(SDLK_i);
107         smallfish.setDown(SDLK_k);
108         smallfish.setLeft(SDLK_j);
109         smallfish.setRight(SDLK_l);
110         result = new Unit(smallfish, ControlSym('u', 'd', 'l', 'r'), true);
111     }
112     else if ("fish_big" == kind) {
113         KeyControl bigfish;
114         bigfish.setUp(SDLK_w);
115         bigfish.setDown(SDLK_s);
116         bigfish.setLeft(SDLK_a);
117         bigfish.setRight(SDLK_d);
118         result = new Unit(bigfish, ControlSym('U', 'D', 'L', 'R'));
119     }
120     else if (StringTool::startsWith(kind, "fish_extra") ||
121         StringTool::startsWith(kind, "fish_EXTRA"))
122     {
123         KeyControl extrafish;
124         extrafish.setUp(SDLK_LAST);
125         extrafish.setDown(SDLK_LAST);
126         extrafish.setLeft(SDLK_LAST);
127         extrafish.setRight(SDLK_LAST);
128         result = new Unit(extrafish, parseExtraControlSym(kind));
129     }
130     return result;
131 }
132 //-----------------------------------------------------------------
133 /**
134  * Create special model, which will be used for outher space.
135  * NOTE: hack border around field
136  */
137     Cube *
createBorder()138 ModelFactory::createBorder()
139 {
140     Cube *border = new Cube(V2(-1,-1), Cube::FIXED, Cube::NONE, false,
141             new Shape("X\n"));
142     return border;
143 }
144 //-----------------------------------------------------------------
145 /**
146  * Create one way output out of room.
147  * @throws LogicException when output_DIR is not known
148  */
149 Cube *
createOutputItem(const std::string & kind,const V2 & loc,const std::string & shape)150 ModelFactory::createOutputItem(const std::string &kind, const V2 &loc,
151         const std::string &shape)
152 {
153     Dir::eDir outDir = Dir::DIR_NO;
154     if ("output_left" == kind) {
155         outDir = Dir::DIR_LEFT;
156     }
157     else if ("output_right" == kind) {
158         outDir = Dir::DIR_RIGHT;
159     }
160     else if ("output_up" == kind) {
161         outDir = Dir::DIR_UP;
162     }
163     else if ("output_down" == kind) {
164         outDir = Dir::DIR_DOWN;
165     }
166     else {
167         throw LogicException(ExInfo("unknown border dir")
168                 .addInfo("kind", kind));
169     }
170 
171     Cube *model = new Cube(loc,
172             Cube::FIXED, Cube::NONE, false, new Shape(shape));
173     model->setOutDir(outDir);
174     return model;
175 }
176 //-----------------------------------------------------------------
177 /**
178  * Define controls symbols for extra fish.
179  * Format: "fish_extra-UDLR"
180  * @throws LogicException when symbols are not specified
181  */
182 ControlSym
parseExtraControlSym(const std::string & kind)183 ModelFactory::parseExtraControlSym(const std::string &kind)
184 {
185     static const std::string PREFIX = "fish_extra-";
186     if (kind.size() != PREFIX.size() + 4) {
187         throw LogicException(ExInfo("you must specify control symbols")
188                 .addInfo("kind", kind));
189     }
190 
191     char up = kind[PREFIX.size()];
192     char down = kind[PREFIX.size() + 1];
193     char left = kind[PREFIX.size() + 2];
194     char right = kind[PREFIX.size() + 3];
195     return ControlSym(up, down, left, right);
196 }
197 
198