summaryrefslogtreecommitdiff
path: root/digital/io-hub/src/robospierre/logistic.h
blob: 0a07647705447ec6a12a85e3916b1b5e99e1ca69 (plain)
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
#ifndef logistic_h
#define logistic_h
/* logistic.h */
/* robospierre - Eurobot 2011 AI. {{{
 *
 * Copyright (C) 2011 Nicolas Schodet
 *
 * APBTeam:
 *        Web: http://apbteam.org/
 *      Email: team AT apbteam DOT org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * }}} */
#include "element.h"
#include "clamp.h"

/** Defines for logistic macro, see LOGISTIC_CASE. */
/** Any element must be present (not empty). */
#define LOG_a 0
/** Do not care if there is an element or not. */
#define LOG__ 1
/** There must not be element here. */
#define LOG_e 2
/** Pawn to pick up. */
#define LOG_P 4
/** A head to pick up. */
#define LOG_H 5
/** Pawn who has to be present. */
#define LOG_p 6
/** Head who has to be present. */
#define LOG_h 7
/** Destination (who has to be empty). */
#define LOG_D 8
/** We have a tower (always at bottom). */
#define LOG_t 9
/* LEFT means we keep the same side, RIGHT means we put the opposed side. */
#define LOG_DIR_LEFT 0
#define LOG_DIR_RIGHT 1
/** Logistic macro to test if a case correspond and to perform movement.
  * We have to consider that the moving direction is on the left.
  * New direction is indicated (same or opposed).
  * Set ready or not. */
#define LOGISTIC_CASE(e1,       e2, \
		      e3,  e4,  e5, \
		      e6,       e7, new_dir, ready) \
{ \
    if (logistic_case (LOG_##e1, LOG_##e2, LOG_##e3, LOG_##e4, LOG_##e5, \
		       LOG_##e6, LOG_##e7, LOG_DIR_##new_dir, ready, 0)) \
    return; \
}

/** Logistic context. */
struct logistic_t
{
    /** Current robot content.
     *
     * Elements are fully specified (pawn, queen or king).  An exception can
     * occurs when a codebar is read but does not correspond to a valid word.
     *
     * When a movement is outgoing, the element is kept in the source slot. */
    uint8_t slots[CLAMP_SLOT_NB];
    /** Current element movement source and destination, CLAMP_SLOT_NB if no
     * current movement. */
    uint8_t moving_from, moving_to;
    /** Best collect direction. */
    uint8_t collect_direction;
    /** Idle clamp position, depend on collect direction. */
    uint8_t clamp_pos_idle;
    /** Inform TOP if no construct is possible (0), if a tower is possible (1), if an
     * other element can be put even if the clamp is broken (2). */
    uint8_t construct_possible;
    /** TOP set 0 if we do not want to build something, 1 if we can build a tower, 2 to prepare
      anything possible, 3 the clamp is broken, prepare anything with *_BOTTOM. */
    uint8_t prepare;
    /** Inform TOP if a construct is ready (1) or not (0). */
    uint8_t ready;
    /* Inform TOP that we can't take any more elements and needs to put
     * construction somewhere. */
    uint8_t need_prepare;
    /** Filtered side slot sensor. */
    uint8_t side_state;
    /** Filtered side slot sensor counter. */
    uint16_t side_filter;
};

/** Global context. */
extern struct logistic_t logistic_global;

/** Initialise module. */
void
logistic_init (void);

/** Examine current state and take a decision. */
void
logistic_decision (void);

/** To be called at regular interval to check for bad robot state. */
void
logistic_update (void);

/** To be called when a new element is entering the robot. */
void
logistic_element_new (uint8_t pos, uint8_t element_type);

/** Oh la la, the pawn was not a pawn, it's a head. */
void
logistic_element_change (uint8_t pos, uint8_t element_type);

/** To be called when a element movement is done. */
void
logistic_element_move_done (void);

/** To be called when elements have been dropped on the opposite side of
 * direction. */
void
logistic_drop (uint8_t direction);

/** Get element type to be dropped. */
uint8_t
logistic_drop_element_type (uint8_t direction);

/** Dump every element. */
void
logistic_dump (void);

/** Is path clear between two positions? */
uint8_t
logistic_path_clear (uint8_t slot1, uint8_t slot2);

#endif /* logistic_h */